summaryrefslogtreecommitdiffstats
path: root/init/bootchart.c
diff options
context:
space:
mode:
Diffstat (limited to 'init/bootchart.c')
-rw-r--r--init/bootchart.c378
1 files changed, 0 insertions, 378 deletions
diff --git a/init/bootchart.c b/init/bootchart.c
deleted file mode 100644
index f72fcaa..0000000
--- a/init/bootchart.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* this code is used to generate a boot sequence profile that can be used
- * with the 'bootchart' graphics generation tool. see www.bootchart.org
- * note that unlike the original bootchartd, this is not a Bash script but
- * some C code that is run right from the init script.
- */
-
-#include <stdio.h>
-#include <time.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include "bootchart.h"
-
-#define VERSION "0.8"
-#define SAMPLE_PERIOD 0.2
-#define LOG_ROOT "/data/bootchart"
-#define LOG_STAT LOG_ROOT"/proc_stat.log"
-#define LOG_PROCS LOG_ROOT"/proc_ps.log"
-#define LOG_DISK LOG_ROOT"/proc_diskstats.log"
-#define LOG_HEADER LOG_ROOT"/header"
-#define LOG_ACCT LOG_ROOT"/kernel_pacct"
-
-#define LOG_STARTFILE "/data/bootchart-start"
-#define LOG_STOPFILE "/data/bootchart-stop"
-
-static int
-unix_read(int fd, void* buff, int len)
-{
- int ret;
- do { ret = read(fd, buff, len); } while (ret < 0 && errno == EINTR);
- return ret;
-}
-
-static int
-unix_write(int fd, const void* buff, int len)
-{
- int ret;
- do { ret = write(fd, buff, len); } while (ret < 0 && errno == EINTR);
- return ret;
-}
-
-static int
-proc_read(const char* filename, char* buff, size_t buffsize)
-{
- int len = 0;
- int fd = open(filename, O_RDONLY);
- if (fd >= 0) {
- len = unix_read(fd, buff, buffsize-1);
- close(fd);
- }
- buff[len > 0 ? len : 0] = 0;
- return len;
-}
-
-#define FILE_BUFF_SIZE 65536
-
-typedef struct {
- int count;
- int fd;
- char data[FILE_BUFF_SIZE];
-} FileBuffRec, *FileBuff;
-
-static void
-file_buff_open( FileBuff buff, const char* path )
-{
- buff->count = 0;
- buff->fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0755);
-}
-
-static void
-file_buff_write( FileBuff buff, const void* src, int len )
-{
- while (len > 0) {
- int avail = sizeof(buff->data) - buff->count;
- if (avail > len)
- avail = len;
-
- memcpy( buff->data + buff->count, src, avail );
- len -= avail;
- src = (char*)src + avail;
-
- buff->count += avail;
- if (buff->count == FILE_BUFF_SIZE) {
- unix_write( buff->fd, buff->data, buff->count );
- buff->count = 0;
- }
- }
-}
-
-static void
-file_buff_done( FileBuff buff )
-{
- if (buff->count > 0) {
- unix_write( buff->fd, buff->data, buff->count );
- buff->count = 0;
- }
-}
-
-static void
-log_header(void)
-{
- FILE* out;
- char cmdline[1024];
- char uname[128];
- char cpuinfo[128];
- char* cpu;
- char date[32];
- time_t now_t = time(NULL);
- struct tm now = *localtime(&now_t);
- strftime(date, sizeof(date), "%x %X", &now);
-
- out = fopen( LOG_HEADER, "w" );
- if (out == NULL)
- return;
-
- proc_read("/proc/cmdline", cmdline, sizeof(cmdline));
- proc_read("/proc/version", uname, sizeof(uname));
- proc_read("/proc/cpuinfo", cpuinfo, sizeof(cpuinfo));
-
- cpu = strchr( cpuinfo, ':' );
- if (cpu) {
- char* p = strchr(cpu, '\n');
- cpu += 2;
- if (p)
- *p = 0;
- }
-
- fprintf(out, "version = %s\n", VERSION);
- fprintf(out, "title = Boot chart for Android ( %s )\n", date);
- fprintf(out, "system.uname = %s\n", uname);
- fprintf(out, "system.release = 0.0\n");
- fprintf(out, "system.cpu = %s\n", cpu);
- fprintf(out, "system.kernel.options = %s\n", cmdline);
- fclose(out);
-}
-
-static void
-close_on_exec(int fd)
-{
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-}
-
-static void
-open_log_file(int* plogfd, const char* logfile)
-{
- int logfd = *plogfd;
-
- /* create log file if needed */
- if (logfd < 0)
- {
- logfd = open(logfile,O_WRONLY|O_CREAT|O_TRUNC,0755);
- if (logfd < 0) {
- *plogfd = -2;
- return;
- }
- close_on_exec(logfd);
- *plogfd = logfd;
- }
-}
-
-static void
-do_log_uptime(FileBuff log)
-{
- char buff[65];
- int fd, ret, len;
-
- fd = open("/proc/uptime",O_RDONLY);
- if (fd >= 0) {
- int ret;
- ret = unix_read(fd, buff, 64);
- close(fd);
- buff[64] = 0;
- if (ret >= 0) {
- long long jiffies = 100LL*strtod(buff,NULL);
- int len;
- snprintf(buff,sizeof(buff),"%lld\n",jiffies);
- len = strlen(buff);
- file_buff_write(log, buff, len);
- }
- }
-}
-
-static void
-do_log_ln(FileBuff log)
-{
- file_buff_write(log, "\n", 1);
-}
-
-
-static void
-do_log_file(FileBuff log, const char* procfile)
-{
- char buff[1024];
- int fd;
-
- do_log_uptime(log);
-
- /* append file content */
- fd = open(procfile,O_RDONLY);
- if (fd >= 0) {
- close_on_exec(fd);
- for (;;) {
- int ret;
- ret = unix_read(fd, buff, sizeof(buff));
- if (ret <= 0)
- break;
-
- file_buff_write(log, buff, ret);
- if (ret < (int)sizeof(buff))
- break;
- }
- close(fd);
- }
-
- do_log_ln(log);
-}
-
-static void
-do_log_procs(FileBuff log)
-{
- DIR* dir = opendir("/proc");
- struct dirent* entry;
-
- do_log_uptime(log);
-
- while ((entry = readdir(dir)) != NULL) {
- /* only match numeric values */
- char* end;
- int pid = strtol( entry->d_name, &end, 10);
- if (end != NULL && end > entry->d_name && *end == 0) {
- char filename[32];
- char buff[1024];
- char cmdline[1024];
- int len;
- int fd;
-
- /* read command line and extract program name */
- snprintf(filename,sizeof(filename),"/proc/%d/cmdline",pid);
- proc_read(filename, cmdline, sizeof(cmdline));
-
- /* read process stat line */
- snprintf(filename,sizeof(filename),"/proc/%d/stat",pid);
- fd = open(filename,O_RDONLY);
- if (fd >= 0) {
- len = unix_read(fd, buff, sizeof(buff)-1);
- close(fd);
- if (len > 0) {
- int len2 = strlen(cmdline);
- if (len2 > 0) {
- /* we want to substitute the process name with its real name */
- const char* p1;
- const char* p2;
- buff[len] = 0;
- p1 = strchr(buff, '(');
- p2 = strchr(p1, ')');
- file_buff_write(log, buff, p1+1-buff);
- file_buff_write(log, cmdline, strlen(cmdline));
- file_buff_write(log, p2, strlen(p2));
- } else {
- /* no substitution */
- file_buff_write(log,buff,len);
- }
- }
- }
- }
- }
- closedir(dir);
- do_log_ln(log);
-}
-
-static FileBuffRec log_stat[1];
-static FileBuffRec log_procs[1];
-static FileBuffRec log_disks[1];
-
-/* called to setup bootcharting */
-int bootchart_init( void )
-{
- int ret;
- char buff[4];
- int timeout = 0, count = 0;
-
- buff[0] = 0;
- proc_read( LOG_STARTFILE, buff, sizeof(buff) );
- if (buff[0] != 0) {
- timeout = atoi(buff);
- }
- else {
- /* when running with emulator, androidboot.bootchart=<timeout>
- * might be passed by as kernel parameters to specify the bootchart
- * timeout. this is useful when using -wipe-data since the /data
- * partition is fresh
- */
- char cmdline[1024];
- char* s;
-#define KERNEL_OPTION "androidboot.bootchart="
- proc_read( "/proc/cmdline", cmdline, sizeof(cmdline) );
- s = strstr(cmdline, KERNEL_OPTION);
- if (s) {
- s += sizeof(KERNEL_OPTION)-1;
- timeout = atoi(s);
- }
- }
- if (timeout == 0)
- return 0;
-
- if (timeout > BOOTCHART_MAX_TIME_SEC)
- timeout = BOOTCHART_MAX_TIME_SEC;
-
- count = (timeout*1000 + BOOTCHART_POLLING_MS-1)/BOOTCHART_POLLING_MS;
-
- do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR);
-
- file_buff_open(log_stat, LOG_STAT);
- file_buff_open(log_procs, LOG_PROCS);
- file_buff_open(log_disks, LOG_DISK);
-
- /* create kernel process accounting file */
- {
- int fd = open( LOG_ACCT, O_WRONLY|O_CREAT|O_TRUNC,0644);
- if (fd >= 0) {
- close(fd);
- acct( LOG_ACCT );
- }
- }
-
- log_header();
- return count;
-}
-
-/* called each time you want to perform a bootchart sampling op */
-int bootchart_step( void )
-{
- do_log_file(log_stat, "/proc/stat");
- do_log_file(log_disks, "/proc/diskstats");
- do_log_procs(log_procs);
-
- /* we stop when /data/bootchart-stop contains 1 */
- {
- char buff[2];
- if (proc_read(LOG_STOPFILE,buff,sizeof(buff)) > 0 && buff[0] == '1') {
- return -1;
- }
- }
-
- return 0;
-}
-
-void bootchart_finish( void )
-{
- unlink( LOG_STOPFILE );
- file_buff_done(log_stat);
- file_buff_done(log_disks);
- file_buff_done(log_procs);
- acct(NULL);
-}