diff options
Diffstat (limited to 'init/bootchart.c')
-rw-r--r-- | init/bootchart.c | 378 |
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); -} |