1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* this code is used to generate a boot sequence profile that can be used
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * with the 'bootchart' graphics generation tool. see www.bootchart.org
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * note that unlike the original bootchartd, this is not a Bash script but
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * some C code that is run right from the init script.
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <time.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h>
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "bootchart.h"
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define VERSION         "0.8"
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define SAMPLE_PERIOD   0.2
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_ROOT        "/data/bootchart"
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_STAT        LOG_ROOT"/proc_stat.log"
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_PROCS       LOG_ROOT"/proc_ps.log"
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_DISK        LOG_ROOT"/proc_diskstats.log"
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_HEADER      LOG_ROOT"/header"
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_ACCT        LOG_ROOT"/kernel_pacct"
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_STARTFILE   "/data/bootchart-start"
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_STOPFILE    "/data/bootchart-stop"
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunix_read(int  fd, void*  buff, int  len)
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  ret;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do { ret = read(fd, buff, len); } while (ret < 0 && errno == EINTR);
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ret;
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunix_write(int  fd, const void*  buff, int  len)
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  ret;
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do { ret = write(fd, buff, len); } while (ret < 0 && errno == EINTR);
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ret;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectproc_read(const char*  filename, char* buff, size_t  buffsize)
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  len = 0;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  fd  = open(filename, O_RDONLY);
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd >= 0) {
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len = unix_read(fd, buff, buffsize-1);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(fd);
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    buff[len > 0 ? len : 0] = 0;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return len;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FILE_BUFF_SIZE    65536
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct {
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int   count;
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int   fd;
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char  data[FILE_BUFF_SIZE];
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} FileBuffRec, *FileBuff;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfile_buff_open( FileBuff  buff, const char*  path )
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    buff->count = 0;
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    buff->fd    = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0755);
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfile_buff_write( FileBuff  buff, const void*  src, int  len )
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (len > 0) {
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  avail = sizeof(buff->data) - buff->count;
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (avail > len)
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            avail = len;
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memcpy( buff->data + buff->count, src, avail );
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len -= avail;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        src  = (char*)src + avail;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        buff->count += avail;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (buff->count == FILE_BUFF_SIZE) {
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            unix_write( buff->fd, buff->data, buff->count );
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            buff->count = 0;
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfile_buff_done( FileBuff  buff )
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (buff->count > 0) {
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        unix_write( buff->fd, buff->data, buff->count );
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        buff->count = 0;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectlog_header(void)
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FILE*      out;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char       cmdline[1024];
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char       uname[128];
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char       cpuinfo[128];
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char*      cpu;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char       date[32];
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    time_t     now_t = time(NULL);
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct tm  now = *localtime(&now_t);
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strftime(date, sizeof(date), "%x %X", &now);
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    out = fopen( LOG_HEADER, "w" );
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (out == NULL)
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc_read("/proc/cmdline", cmdline, sizeof(cmdline));
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc_read("/proc/version", uname, sizeof(uname));
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc_read("/proc/cpuinfo", cpuinfo, sizeof(cpuinfo));
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cpu = strchr( cpuinfo, ':' );
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (cpu) {
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char*  p = strchr(cpu, '\n');
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cpu += 2;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (p)
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *p = 0;
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(out, "version = %s\n", VERSION);
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(out, "title = Boot chart for Android ( %s )\n", date);
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(out, "system.uname = %s\n", uname);
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(out, "system.release = 0.0\n");
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(out, "system.cpu = %s\n", cpu);
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(out, "system.kernel.options = %s\n", cmdline);
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fclose(out);
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectclose_on_exec(int  fd)
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fcntl(fd, F_SETFD, FD_CLOEXEC);
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectopen_log_file(int*  plogfd, const char*  logfile)
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int    logfd = *plogfd;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* create log file if needed */
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (logfd < 0)
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        logfd = open(logfile,O_WRONLY|O_CREAT|O_TRUNC,0755);
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (logfd < 0) {
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *plogfd = -2;
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close_on_exec(logfd);
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *plogfd = logfd;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdo_log_uptime(FileBuff  log)
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char  buff[65];
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int   fd, ret, len;
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open("/proc/uptime",O_RDONLY);
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd >= 0) {
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  ret;
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = unix_read(fd, buff, 64);
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(fd);
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        buff[64] = 0;
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ret >= 0) {
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            long long  jiffies = 100LL*strtod(buff,NULL);
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int        len;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            snprintf(buff,sizeof(buff),"%lld\n",jiffies);
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            len = strlen(buff);
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            file_buff_write(log, buff, len);
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdo_log_ln(FileBuff  log)
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    file_buff_write(log, "\n", 1);
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdo_log_file(FileBuff  log, const char*  procfile)
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char   buff[1024];
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int    fd;
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do_log_uptime(log);
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* append file content */
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open(procfile,O_RDONLY);
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd >= 0) {
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close_on_exec(fd);
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (;;) {
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int  ret;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ret = unix_read(fd, buff, sizeof(buff));
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (ret <= 0)
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            file_buff_write(log, buff, ret);
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (ret < (int)sizeof(buff))
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(fd);
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do_log_ln(log);
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdo_log_procs(FileBuff  log)
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DIR*  dir = opendir("/proc");
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct dirent*  entry;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do_log_uptime(log);
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while ((entry = readdir(dir)) != NULL) {
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* only match numeric values */
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char*  end;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int    pid = strtol( entry->d_name, &end, 10);
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (end != NULL && end > entry->d_name && *end == 0) {
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char  filename[32];
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char  buff[1024];
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char  cmdline[1024];
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int   len;
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int   fd;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* read command line and extract program name */
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            snprintf(filename,sizeof(filename),"/proc/%d/cmdline",pid);
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            proc_read(filename, cmdline, sizeof(cmdline));
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* read process stat line */
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            snprintf(filename,sizeof(filename),"/proc/%d/stat",pid);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd = open(filename,O_RDONLY);
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fd >= 0) {
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               len = unix_read(fd, buff, sizeof(buff)-1);
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               close(fd);
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               if (len > 0) {
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    int  len2 = strlen(cmdline);
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (len2 > 0) {
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        /* we want to substitute the process name with its real name */
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        const char*  p1;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        const char*  p2;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        buff[len] = 0;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        p1 = strchr(buff, '(');
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        p2 = strchr(p1, ')');
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        file_buff_write(log, buff, p1+1-buff);
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        file_buff_write(log, cmdline, strlen(cmdline));
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        file_buff_write(log, p2, strlen(p2));
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    } else {
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        /* no substitution */
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        file_buff_write(log,buff,len);
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               }
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    closedir(dir);
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do_log_ln(log);
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic FileBuffRec  log_stat[1];
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic FileBuffRec  log_procs[1];
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic FileBuffRec  log_disks[1];
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* called to setup bootcharting */
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint   bootchart_init( void )
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  ret;
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char buff[4];
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  timeout = 0, count = 0;
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    buff[0] = 0;
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    proc_read( LOG_STARTFILE, buff, sizeof(buff) );
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (buff[0] != 0) {
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        timeout = atoi(buff);
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else {
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* when running with emulator, androidboot.bootchart=<timeout>
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         * might be passed by as kernel parameters to specify the bootchart
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         * timeout. this is useful when using -wipe-data since the /data
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         * partition is fresh
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         */
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char  cmdline[1024];
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char* s;
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  KERNEL_OPTION  "androidboot.bootchart="
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        proc_read( "/proc/cmdline", cmdline, sizeof(cmdline) );
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s = strstr(cmdline, KERNEL_OPTION);
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (s) {
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s      += sizeof(KERNEL_OPTION)-1;
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            timeout = atoi(s);
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (timeout == 0)
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (timeout > BOOTCHART_MAX_TIME_SEC)
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        timeout = BOOTCHART_MAX_TIME_SEC;
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    count = (timeout*1000 + BOOTCHART_POLLING_MS-1)/BOOTCHART_POLLING_MS;
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR);
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    file_buff_open(log_stat,  LOG_STAT);
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    file_buff_open(log_procs, LOG_PROCS);
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    file_buff_open(log_disks, LOG_DISK);
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* create kernel process accounting file */
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  fd = open( LOG_ACCT, O_WRONLY|O_CREAT|O_TRUNC,0644);
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (fd >= 0) {
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            close(fd);
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            acct( LOG_ACCT );
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    log_header();
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return count;
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* called each time you want to perform a bootchart sampling op */
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint  bootchart_step( void )
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do_log_file(log_stat,   "/proc/stat");
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do_log_file(log_disks,  "/proc/diskstats");
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do_log_procs(log_procs);
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* we stop when /data/bootchart-stop contains 1 */
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char  buff[2];
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (proc_read(LOG_STOPFILE,buff,sizeof(buff)) > 0 && buff[0] == '1') {
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid  bootchart_finish( void )
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unlink( LOG_STOPFILE );
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    file_buff_done(log_stat);
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    file_buff_done(log_disks);
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    file_buff_done(log_procs);
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    acct(NULL);
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
379