Merge "bootchart: fix bootchart can not be triggered problem"
This commit is contained in:
commit
265df6f50c
8 changed files with 107 additions and 111 deletions
|
|
@ -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)))
|
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
|
||||||
init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_DISABLE_SELINUX=1
|
init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_DISABLE_SELINUX=1
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,31 @@
|
||||||
This version of init contains code to perform "bootcharting", i.e. generating log
|
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.
|
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
|
On the emulator, use the new -bootchart <timeout> option to boot with bootcharting
|
||||||
activated for <timeout> seconds.
|
activated for <timeout> seconds.
|
||||||
|
|
||||||
Otherwise, flash your device, and start it. Then create a file on the /data partition
|
Otherwise, flash your device, and start it. Then create a file on the /data partition
|
||||||
with a command like the following:
|
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;
|
Where the value of $TIMEOUT corresponds to the wanted bootcharted period in seconds;
|
||||||
for example, to bootchart for 2 minutes, do:
|
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.
|
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:
|
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
|
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
|
bootcharting. This is not the case of /data/bootchart/start, so don't forget to delete it
|
||||||
when you're done collecting data:
|
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
|
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:
|
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:
|
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
|
www.bootchart.org, but a C re-implementation that is directly compiled into our init
|
||||||
program.
|
program.
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "bootchart.h"
|
#include "bootchart.h"
|
||||||
|
#include "keywords.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
@ -32,6 +34,10 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.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 VERSION "0.8"
|
||||||
#define SAMPLE_PERIOD 0.2
|
#define SAMPLE_PERIOD 0.2
|
||||||
#define LOG_ROOT "/data/bootchart"
|
#define LOG_ROOT "/data/bootchart"
|
||||||
|
|
@ -41,8 +47,23 @@
|
||||||
#define LOG_HEADER LOG_ROOT"/header"
|
#define LOG_HEADER LOG_ROOT"/header"
|
||||||
#define LOG_ACCT LOG_ROOT"/kernel_pacct"
|
#define LOG_ACCT LOG_ROOT"/kernel_pacct"
|
||||||
|
|
||||||
#define LOG_STARTFILE "/data/bootchart-start"
|
#define LOG_STARTFILE LOG_ROOT"/start"
|
||||||
#define LOG_STOPFILE "/data/bootchart-stop"
|
#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
|
static int
|
||||||
proc_read(const char* filename, char* buff, size_t buffsize)
|
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;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FILE_BUFF_SIZE 65536
|
|
||||||
|
|
||||||
struct FileBuff {
|
|
||||||
int count;
|
|
||||||
int fd;
|
|
||||||
char data[FILE_BUFF_SIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
file_buff_open( FileBuff* buff, const char* path )
|
file_buff_open( FileBuff* buff, const char* path )
|
||||||
{
|
{
|
||||||
buff->count = 0;
|
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
|
static void
|
||||||
|
|
@ -248,9 +261,19 @@ do_log_procs(FileBuff* log)
|
||||||
do_log_ln(log);
|
do_log_ln(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FileBuff log_stat[1];
|
int do_bootchart_init(int nargs, char **args)
|
||||||
static FileBuff log_procs[1];
|
{
|
||||||
static FileBuff log_disks[1];
|
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 */
|
/* called to setup bootcharting */
|
||||||
int bootchart_init( void )
|
int bootchart_init( void )
|
||||||
|
|
@ -307,14 +330,13 @@ int bootchart_init( void )
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called each time you want to perform a bootchart sampling op */
|
static int bootchart_step( void )
|
||||||
int bootchart_step( void )
|
|
||||||
{
|
{
|
||||||
do_log_file(log_stat, "/proc/stat");
|
do_log_file(log_stat, "/proc/stat");
|
||||||
do_log_file(log_disks, "/proc/diskstats");
|
do_log_file(log_disks, "/proc/diskstats");
|
||||||
do_log_procs(log_procs);
|
do_log_procs(log_procs);
|
||||||
|
|
||||||
/* we stop when /data/bootchart-stop contains 1 */
|
/* we stop when /data/bootchart/stop contains 1 */
|
||||||
{
|
{
|
||||||
char buff[2];
|
char buff[2];
|
||||||
if (proc_read(LOG_STOPFILE,buff,sizeof(buff)) > 0 && buff[0] == '1') {
|
if (proc_read(LOG_STOPFILE,buff,sizeof(buff)) > 0 && buff[0] == '1') {
|
||||||
|
|
@ -325,6 +347,42 @@ int bootchart_step( void )
|
||||||
return 0;
|
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 )
|
void bootchart_finish( void )
|
||||||
{
|
{
|
||||||
unlink( LOG_STOPFILE );
|
unlink( LOG_STOPFILE );
|
||||||
|
|
@ -333,9 +391,3 @@ void bootchart_finish( void )
|
||||||
file_buff_done(log_procs);
|
file_buff_done(log_procs);
|
||||||
acct(NULL);
|
acct(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called to get time (in ms) used by bootchart */
|
|
||||||
long long bootchart_gettime( void )
|
|
||||||
{
|
|
||||||
return 10LL*get_uptime_jiffies();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,8 @@
|
||||||
#ifndef _BOOTCHART_H
|
#ifndef _BOOTCHART_H
|
||||||
#define _BOOTCHART_H
|
#define _BOOTCHART_H
|
||||||
|
|
||||||
extern int bootchart_init(void);
|
int bootchart_init();
|
||||||
extern int bootchart_step(void);
|
void bootchart_sample(int* timeout);
|
||||||
extern void bootchart_finish(void);
|
void bootchart_finish();
|
||||||
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 */
|
|
||||||
|
|
||||||
#endif /* _BOOTCHART_H */
|
#endif /* _BOOTCHART_H */
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,6 @@ struct selabel_handle *sehandle_prop;
|
||||||
|
|
||||||
static int property_triggers_enabled = 0;
|
static int property_triggers_enabled = 0;
|
||||||
|
|
||||||
static int bootchart_count;
|
|
||||||
static long long bootchart_time = 0;
|
|
||||||
|
|
||||||
static char console[32];
|
static char console[32];
|
||||||
static char bootmode[32];
|
static char bootmode[32];
|
||||||
static char hardware[32];
|
static char hardware[32];
|
||||||
|
|
@ -857,20 +854,6 @@ static int queue_property_triggers_action(int nargs, char **args)
|
||||||
return 0;
|
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)
|
void selinux_init_all_handles(void)
|
||||||
{
|
{
|
||||||
sehandle = selinux_android_file_context_handle();
|
sehandle = selinux_android_file_context_handle();
|
||||||
|
|
@ -988,7 +971,7 @@ static void selinux_initialize(void)
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int fd_count = 0;
|
size_t fd_count = 0;
|
||||||
struct pollfd ufds[4];
|
struct pollfd ufds[4];
|
||||||
int property_set_fd_init = 0;
|
int property_set_fd_init = 0;
|
||||||
int signal_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 */
|
/* run all property triggers based on current state of the properties */
|
||||||
queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
|
queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
|
||||||
|
|
||||||
if (BOOTCHART) {
|
for (;;) {
|
||||||
queue_builtin_action(bootchart_init_action, "bootchart_init");
|
|
||||||
}
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
int nr, i, timeout = -1;
|
|
||||||
|
|
||||||
execute_one_command();
|
execute_one_command();
|
||||||
restart_processes();
|
restart_processes();
|
||||||
|
|
||||||
|
|
@ -1119,6 +1096,7 @@ int main(int argc, char **argv)
|
||||||
keychord_fd_init = 1;
|
keychord_fd_init = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int timeout = -1;
|
||||||
if (process_needs_restart) {
|
if (process_needs_restart) {
|
||||||
timeout = (process_needs_restart - gettime()) * 1000;
|
timeout = (process_needs_restart - gettime()) * 1000;
|
||||||
if (timeout < 0)
|
if (timeout < 0)
|
||||||
|
|
@ -1129,48 +1107,22 @@ int main(int argc, char **argv)
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BOOTCHART) {
|
bootchart_sample(&timeout);
|
||||||
if (bootchart_count > 0) {
|
|
||||||
long long current_time;
|
|
||||||
int elapsed_time, remaining_time;
|
|
||||||
|
|
||||||
current_time = bootchart_gettime();
|
int nr = poll(ufds, fd_count, timeout);
|
||||||
elapsed_time = current_time - bootchart_time;
|
if (nr <= 0) {
|
||||||
|
continue;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nr = poll(ufds, fd_count, timeout);
|
for (size_t i = 0; i < fd_count; i++) {
|
||||||
if (nr <= 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (i = 0; i < fd_count; i++) {
|
|
||||||
if (ufds[i].revents & POLLIN) {
|
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();
|
handle_property_set_fd();
|
||||||
else if (ufds[i].fd == get_keychord_fd())
|
} else if (ufds[i].fd == get_keychord_fd()) {
|
||||||
handle_keychord();
|
handle_keychord();
|
||||||
else if (ufds[i].fd == get_signal_fd())
|
} else if (ufds[i].fd == get_signal_fd()) {
|
||||||
handle_signal();
|
handle_signal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,8 @@ void dump_parser_state() {
|
||||||
static int lookup_keyword(const char *s)
|
static int lookup_keyword(const char *s)
|
||||||
{
|
{
|
||||||
switch (*s++) {
|
switch (*s++) {
|
||||||
|
case 'b':
|
||||||
|
if (!strcmp(s, "ootchart_init")) return K_bootchart_init;
|
||||||
case 'c':
|
case 'c':
|
||||||
if (!strcmp(s, "opy")) return K_copy;
|
if (!strcmp(s, "opy")) return K_copy;
|
||||||
if (!strcmp(s, "apability")) return K_capability;
|
if (!strcmp(s, "apability")) return K_capability;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#ifndef KEYWORD
|
#ifndef KEYWORD
|
||||||
|
int do_bootchart_init(int nargs, char **args);
|
||||||
int do_chroot(int nargs, char **args);
|
int do_chroot(int nargs, char **args);
|
||||||
int do_chdir(int nargs, char **args);
|
int do_chdir(int nargs, char **args);
|
||||||
int do_class_start(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_persist_props, COMMAND, 0, do_load_persist_props)
|
||||||
KEYWORD(load_all_props, COMMAND, 0, do_load_all_props)
|
KEYWORD(load_all_props, COMMAND, 0, do_load_all_props)
|
||||||
KEYWORD(ioprio, OPTION, 0, 0)
|
KEYWORD(ioprio, OPTION, 0, 0)
|
||||||
|
KEYWORD(bootchart_init, COMMAND, 0, do_bootchart_init)
|
||||||
#ifdef __MAKE_KEYWORD_ENUM__
|
#ifdef __MAKE_KEYWORD_ENUM__
|
||||||
KEYWORD_COUNT,
|
KEYWORD_COUNT,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,11 @@ on post-fs-data
|
||||||
# We restorecon /data in case the userdata partition has been reset.
|
# We restorecon /data in case the userdata partition has been reset.
|
||||||
restorecon /data
|
restorecon /data
|
||||||
|
|
||||||
|
# Start bootcharting as soon as possible after the data partition is
|
||||||
|
# mounted to collect more data.
|
||||||
|
mkdir /data/bootchart 0755 shell shell
|
||||||
|
bootchart_init
|
||||||
|
|
||||||
# Avoid predictable entropy pool. Carry over entropy from previous boot.
|
# Avoid predictable entropy pool. Carry over entropy from previous boot.
|
||||||
copy /data/system/entropy.dat /dev/urandom
|
copy /data/system/entropy.dat /dev/urandom
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue