diff options
Diffstat (limited to 'init')
-rw-r--r-- | init/Android.mk | 6 | ||||
-rw-r--r-- | init/README.BOOTCHART | 22 | ||||
-rw-r--r-- | init/bootchart.cpp | 98 | ||||
-rw-r--r-- | init/bootchart.h | 11 | ||||
-rw-r--r-- | init/init.cpp | 72 | ||||
-rw-r--r-- | init/init_parser.cpp | 2 | ||||
-rw-r--r-- | init/keywords.h | 2 |
7 files changed, 102 insertions, 111 deletions
diff --git a/init/Android.mk b/init/Android.mk index 7f3788a..a3b01e1 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -4,12 +4,6 @@ LOCAL_PATH:= $(call my-dir) # -- -ifeq ($(strip $(INIT_BOOTCHART)),true) -init_options += -DBOOTCHART=1 -else -init_options += -DBOOTCHART=0 -endif - ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_DISABLE_SELINUX=1 else diff --git a/init/README.BOOTCHART b/init/README.BOOTCHART index 70cf2c3..245e452 100644 --- a/init/README.BOOTCHART +++ b/init/README.BOOTCHART @@ -1,37 +1,31 @@ This version of init contains code to perform "bootcharting", i.e. generating log files that can be later processed by the tools provided by www.bootchart.org. -To activate it, you need to define build 'init' with the INIT_BOOTCHART environment -variable defined to 'true', for example: - - touch system/init/init.c - m INIT_BOOTCHART=true - On the emulator, use the new -bootchart <timeout> option to boot with bootcharting activated for <timeout> seconds. Otherwise, flash your device, and start it. Then create a file on the /data partition with a command like the following: - adb shell 'echo $TIMEOUT > /data/bootchart-start' + adb shell 'echo $TIMEOUT > /data/bootchart/start' Where the value of $TIMEOUT corresponds to the wanted bootcharted period in seconds; for example, to bootchart for 2 minutes, do: - adb shell 'echo 120 > /data/bootchart-start' + adb shell 'echo 120 > /data/bootchart/start' Reboot your device, bootcharting will begin and stop after the period you gave. You can also stop the bootcharting at any moment by doing the following: - adb shell 'echo 1 > /data/bootchart-stop' + adb shell 'echo 1 > /data/bootchart/stop' -Note that /data/bootchart-stop is deleted automatically by init at the end of the -bootcharting. This is not the case of /data/bootchart-start, so don't forget to delete it +Note that /data/bootchart/stop is deleted automatically by init at the end of the +bootcharting. This is not the case of /data/bootchart/start, so don't forget to delete it when you're done collecting data: - adb shell rm /data/bootchart-start + adb shell rm /data/bootchart/start -The log files are placed in /data/bootchart/. you must run the script tools/grab-bootchart.sh +The log files are placed in /data/bootchart/. You must run the script tools/grab-bootchart.sh which will use ADB to retrieve them and create a bootchart.tgz file that can be used with the bootchart parser/renderer, or even uploaded directly to the form located at: @@ -47,6 +41,6 @@ NOTE: the bootchart.org webform doesn't seem to work at the moment, you can gene technical note: -this implementation of bootcharting does use the 'bootchartd' script provided by +This implementation of bootcharting does not use the 'bootchartd' script provided by www.bootchart.org, but a C re-implementation that is directly compiled into our init program. diff --git a/init/bootchart.cpp b/init/bootchart.cpp index d275096..ff4c0cf 100644 --- a/init/bootchart.cpp +++ b/init/bootchart.cpp @@ -21,6 +21,8 @@ */ #include "bootchart.h" +#include "keywords.h" +#include "log.h" #include <dirent.h> #include <errno.h> @@ -32,6 +34,10 @@ #include <time.h> #include <unistd.h> +#define BOOTCHART_POLLING_MS 200 /* polling period in ms */ +#define BOOTCHART_DEFAULT_TIME_SEC (2*60) /* default polling time in seconds */ +#define BOOTCHART_MAX_TIME_SEC (10*60) /* max polling time in seconds */ + #define VERSION "0.8" #define SAMPLE_PERIOD 0.2 #define LOG_ROOT "/data/bootchart" @@ -41,8 +47,23 @@ #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" +#define LOG_STARTFILE LOG_ROOT"/start" +#define LOG_STOPFILE LOG_ROOT"/stop" + +#define FILE_BUFF_SIZE 65536 + +struct FileBuff { + int count; + int fd; + char data[FILE_BUFF_SIZE]; +}; + +static long long last_bootchart_time; +static int g_remaining_samples; + +static FileBuff log_stat[1]; +static FileBuff log_procs[1]; +static FileBuff log_disks[1]; static int proc_read(const char* filename, char* buff, size_t buffsize) @@ -57,19 +78,11 @@ proc_read(const char* filename, char* buff, size_t buffsize) return len; } -#define FILE_BUFF_SIZE 65536 - -struct FileBuff { - int count; - int fd; - char data[FILE_BUFF_SIZE]; -}; - static void file_buff_open( FileBuff* buff, const char* path ) { buff->count = 0; - buff->fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0755); + buff->fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0755); } static void @@ -248,9 +261,19 @@ do_log_procs(FileBuff* log) do_log_ln(log); } -static FileBuff log_stat[1]; -static FileBuff log_procs[1]; -static FileBuff log_disks[1]; +int do_bootchart_init(int nargs, char **args) +{ + g_remaining_samples = bootchart_init(); + if (g_remaining_samples < 0) { + ERROR("bootcharting init failure\n"); + } else if (g_remaining_samples > 0) { + NOTICE("bootcharting started (will run for %d ms)\n", g_remaining_samples*BOOTCHART_POLLING_MS); + } else { + NOTICE("bootcharting ignored\n"); + } + + return 0; +} /* called to setup bootcharting */ int bootchart_init( void ) @@ -307,14 +330,13 @@ int bootchart_init( void ) return count; } -/* called each time you want to perform a bootchart sampling op */ -int bootchart_step( void ) +static 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 */ + /* we stop when /data/bootchart/stop contains 1 */ { char buff[2]; if (proc_read(LOG_STOPFILE,buff,sizeof(buff)) > 0 && buff[0] == '1') { @@ -325,6 +347,42 @@ int bootchart_step( void ) return 0; } +/* called to get time (in ms) used by bootchart */ +static long long bootchart_gettime() { + return 10LL*get_uptime_jiffies(); +} + +/* called each time you want to perform a bootchart sampling op */ +void bootchart_sample(int* timeout) { + if (g_remaining_samples > 0) { + long long current_time; + int elapsed_time, remaining_time; + + current_time = bootchart_gettime(); + elapsed_time = current_time - last_bootchart_time; + + if (elapsed_time >= BOOTCHART_POLLING_MS) { + /* count missed samples */ + while (elapsed_time >= BOOTCHART_POLLING_MS) { + elapsed_time -= BOOTCHART_POLLING_MS; + g_remaining_samples--; + } + /* count may be negative, take a sample anyway */ + last_bootchart_time = current_time; + if (bootchart_step() < 0 || g_remaining_samples <= 0) { + bootchart_finish(); + g_remaining_samples = 0; + } + } + if (g_remaining_samples > 0) { + remaining_time = BOOTCHART_POLLING_MS - elapsed_time; + if (*timeout < 0 || *timeout > remaining_time) { + *timeout = remaining_time; + } + } + } +} + void bootchart_finish( void ) { unlink( LOG_STOPFILE ); @@ -333,9 +391,3 @@ void bootchart_finish( void ) file_buff_done(log_procs); acct(NULL); } - -/* called to get time (in ms) used by bootchart */ -long long bootchart_gettime( void ) -{ - return 10LL*get_uptime_jiffies(); -} diff --git a/init/bootchart.h b/init/bootchart.h index 9ba3c40..7842950 100644 --- a/init/bootchart.h +++ b/init/bootchart.h @@ -17,13 +17,8 @@ #ifndef _BOOTCHART_H #define _BOOTCHART_H -extern int bootchart_init(void); -extern int bootchart_step(void); -extern void bootchart_finish(void); -extern long long bootchart_gettime(void); - -#define BOOTCHART_POLLING_MS 200 /* polling period in ms */ -#define BOOTCHART_DEFAULT_TIME_SEC (2*60) /* default polling time in seconds */ -#define BOOTCHART_MAX_TIME_SEC (10*60) /* max polling time in seconds */ +int bootchart_init(); +void bootchart_sample(int* timeout); +void bootchart_finish(); #endif /* _BOOTCHART_H */ diff --git a/init/init.cpp b/init/init.cpp index 3e3be2e..8647496 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -63,9 +63,6 @@ struct selabel_handle *sehandle_prop; static int property_triggers_enabled = 0; -static int bootchart_count; -static long long bootchart_time = 0; - static char console[32]; static char bootmode[32]; static char hardware[32]; @@ -857,20 +854,6 @@ static int queue_property_triggers_action(int nargs, char **args) return 0; } -static int bootchart_init_action(int nargs, char **args) -{ - bootchart_count = bootchart_init(); - if (bootchart_count < 0) { - ERROR("bootcharting init failure\n"); - } else if (bootchart_count > 0) { - NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS); - } else { - NOTICE("bootcharting ignored\n"); - } - - return 0; -} - void selinux_init_all_handles(void) { sehandle = selinux_android_file_context_handle(); @@ -988,7 +971,7 @@ static void selinux_initialize(void) int main(int argc, char **argv) { - int fd_count = 0; + size_t fd_count = 0; struct pollfd ufds[4]; int property_set_fd_init = 0; int signal_fd_init = 0; @@ -1087,13 +1070,7 @@ int main(int argc, char **argv) /* run all property triggers based on current state of the properties */ queue_builtin_action(queue_property_triggers_action, "queue_property_triggers"); - if (BOOTCHART) { - queue_builtin_action(bootchart_init_action, "bootchart_init"); - } - - for(;;) { - int nr, i, timeout = -1; - + for (;;) { execute_one_command(); restart_processes(); @@ -1119,6 +1096,7 @@ int main(int argc, char **argv) keychord_fd_init = 1; } + int timeout = -1; if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) @@ -1129,48 +1107,22 @@ int main(int argc, char **argv) timeout = 0; } - if (BOOTCHART) { - if (bootchart_count > 0) { - long long current_time; - int elapsed_time, remaining_time; - - current_time = bootchart_gettime(); - elapsed_time = current_time - bootchart_time; - - if (elapsed_time >= BOOTCHART_POLLING_MS) { - /* count missed samples */ - while (elapsed_time >= BOOTCHART_POLLING_MS) { - elapsed_time -= BOOTCHART_POLLING_MS; - bootchart_count--; - } - /* count may be negative, take a sample anyway */ - bootchart_time = current_time; - if (bootchart_step() < 0 || bootchart_count <= 0) { - bootchart_finish(); - bootchart_count = 0; - } - } - if (bootchart_count > 0) { - remaining_time = BOOTCHART_POLLING_MS - elapsed_time; - if (timeout < 0 || timeout > remaining_time) { - timeout = remaining_time; - } - } - } - } + bootchart_sample(&timeout); - nr = poll(ufds, fd_count, timeout); - if (nr <= 0) + int nr = poll(ufds, fd_count, timeout); + if (nr <= 0) { continue; + } - for (i = 0; i < fd_count; i++) { + for (size_t i = 0; i < fd_count; i++) { if (ufds[i].revents & POLLIN) { - if (ufds[i].fd == get_property_set_fd()) + if (ufds[i].fd == get_property_set_fd()) { handle_property_set_fd(); - else if (ufds[i].fd == get_keychord_fd()) + } else if (ufds[i].fd == get_keychord_fd()) { handle_keychord(); - else if (ufds[i].fd == get_signal_fd()) + } else if (ufds[i].fd == get_signal_fd()) { handle_signal(); + } } } } diff --git a/init/init_parser.cpp b/init/init_parser.cpp index 65fc1a6..61a5e0a 100644 --- a/init/init_parser.cpp +++ b/init/init_parser.cpp @@ -115,6 +115,8 @@ void dump_parser_state() { static int lookup_keyword(const char *s) { switch (*s++) { + case 'b': + if (!strcmp(s, "ootchart_init")) return K_bootchart_init; case 'c': if (!strcmp(s, "opy")) return K_copy; if (!strcmp(s, "apability")) return K_capability; diff --git a/init/keywords.h b/init/keywords.h index 0805cdd..a8f29d1 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -1,4 +1,5 @@ #ifndef KEYWORD +int do_bootchart_init(int nargs, char **args); int do_chroot(int nargs, char **args); int do_chdir(int nargs, char **args); int do_class_start(int nargs, char **args); @@ -105,6 +106,7 @@ enum { KEYWORD(load_persist_props, COMMAND, 0, do_load_persist_props) KEYWORD(load_all_props, COMMAND, 0, do_load_all_props) KEYWORD(ioprio, OPTION, 0, 0) + KEYWORD(bootchart_init, COMMAND, 0, do_bootchart_init) #ifdef __MAKE_KEYWORD_ENUM__ KEYWORD_COUNT, }; |