summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
Diffstat (limited to 'init')
-rw-r--r--init/Android.mk6
-rw-r--r--init/README.BOOTCHART22
-rw-r--r--init/bootchart.cpp98
-rw-r--r--init/bootchart.h11
-rw-r--r--init/init.cpp72
-rw-r--r--init/init_parser.cpp2
-rw-r--r--init/keywords.h2
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,
};