init: Handle commands in event queue loop
Change-Id: I679059dae43143f3c8f16b68de5694539b699e50
diff --git a/init/init.c b/init/init.c
index 3d619b9..936880a 100755
--- a/init/init.c
+++ b/init/init.c
@@ -63,6 +63,10 @@
static unsigned revision = 0;
static char qemu[32];
+static struct action *cur_action = NULL;
+static struct command *cur_command = NULL;
+static struct listnode *command_queue = NULL;
+
void notify_service_state(const char *name, const char *state)
{
char pname[PROP_NAME_MAX];
@@ -301,10 +305,8 @@
void property_changed(const char *name, const char *value)
{
- if (property_triggers_enabled) {
+ if (property_triggers_enabled)
queue_property_triggers(name, value);
- drain_action_queue();
- }
}
static void restart_service_if_needed(struct service *svc)
@@ -494,21 +496,52 @@
}
}
-void drain_action_queue(void)
+static struct command *get_first_command(struct action *act)
{
struct listnode *node;
- struct command *cmd;
- struct action *act;
+ node = list_head(&act->commands);
+ if (!node)
+ return NULL;
+
+ return node_to_item(node, struct command, clist);
+}
+
+static struct command *get_next_command(struct action *act, struct command *cmd)
+{
+ struct listnode *node;
+ node = cmd->clist.next;
+ if (!node)
+ return NULL;
+ if (node == &act->commands)
+ return NULL;
+
+ return node_to_item(node, struct command, clist);
+}
+
+static int is_last_command(struct action *act, struct command *cmd)
+{
+ return (list_tail(&act->commands) == &cmd->clist);
+}
+
+void execute_one_command(void)
+{
int ret;
- while ((act = action_remove_queue_head())) {
- INFO("processing action %p (%s)\n", act, act->name);
- list_for_each(node, &act->commands) {
- cmd = node_to_item(node, struct command, clist);
- ret = cmd->func(cmd->nargs, cmd->args);
- INFO("command '%s' r=%d\n", cmd->args[0], ret);
- }
+ if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {
+ cur_action = action_remove_queue_head();
+ if (!cur_action)
+ return;
+ INFO("processing action %p (%s)\n", cur_action, cur_action->name);
+ cur_command = get_first_command(cur_action);
+ } else {
+ cur_command = get_next_command(cur_action, cur_command);
}
+
+ if (!cur_command)
+ return;
+
+ ret = cur_command->func(cur_command->nargs, cur_command->args);
+ INFO("command '%s' r=%d\n", cur_command->args[0], ret);
}
void open_devnull_stdio(void)
@@ -532,16 +565,155 @@
exit(1);
}
+static int device_init_action(int nargs, char **args)
+{
+ INFO("device init\n");
+ device_init();
+ return 0;
+}
+
+static int property_init_action(int nargs, char **args)
+{
+ INFO("property init\n");
+ property_init();
+ return 0;
+}
+
+static int keychord_init_action(int nargs, char **args)
+{
+ keychord_init();
+ return 0;
+}
+
+static int console_init_action(int nargs, char **args)
+{
+ int fd;
+ char tmp[PROP_VALUE_MAX];
+
+ if (console[0]) {
+ snprintf(tmp, sizeof(tmp), "/dev/%s", console);
+ console_name = strdup(tmp);
+ }
+
+ fd = open(console_name, O_RDWR);
+ if (fd >= 0)
+ have_console = 1;
+ close(fd);
+
+ if( load_565rle_image(INIT_IMAGE_FILE) ) {
+ fd = open("/dev/tty0", O_WRONLY);
+ if (fd >= 0) {
+ const char *msg;
+ msg = "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n" // console is 40 cols x 30 lines
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ " A N D R O I D ";
+ write(fd, msg, strlen(msg));
+ close(fd);
+ }
+ }
+ return 0;
+}
+
+static int set_init_properties_action(int nargs, char **args)
+{
+ char tmp[PROP_VALUE_MAX];
+
+ if (qemu[0])
+ import_kernel_cmdline(1);
+
+ if (!strcmp(bootmode,"factory"))
+ property_set("ro.factorytest", "1");
+ else if (!strcmp(bootmode,"factory2"))
+ property_set("ro.factorytest", "2");
+ else
+ property_set("ro.factorytest", "0");
+
+ property_set("ro.serialno", serialno[0] ? serialno : "");
+ property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
+ property_set("ro.baseband", baseband[0] ? baseband : "unknown");
+ property_set("ro.carrier", carrier[0] ? carrier : "unknown");
+ property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
+
+ property_set("ro.hardware", hardware);
+ snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
+ property_set("ro.revision", tmp);
+ return 0;
+}
+
+static int property_service_init_action(int nargs, char **args)
+{
+ /* read any property files on system or data and
+ * fire up the property service. This must happen
+ * after the ro.foo properties are set above so
+ * that /data/local.prop cannot interfere with them.
+ */
+ start_property_service();
+ return 0;
+}
+
+static int signal_init_action(int nargs, char **args)
+{
+ signal_init();
+ return 0;
+}
+
+static int check_startup_action(int nargs, char **args)
+{
+ /* make sure we actually have all the pieces we need */
+ if ((get_device_fd() < 0) ||
+ (get_property_set_fd() < 0) ||
+ (get_signal_fd() < 0)) {
+ ERROR("init startup failure\n");
+ exit(1);
+ }
+ return 0;
+}
+
+static int queue_property_triggers_action(int nargs, char **args)
+{
+ queue_all_property_triggers();
+ /* enable property triggers */
+ property_triggers_enabled = 1;
+ return 0;
+}
+
+#if BOOTCHART
+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");
+ }
+}
+#endif
+
int main(int argc, char **argv)
{
- int fd_count;
- int s[2];
- int fd;
- struct sigaction act;
- char tmp[PROP_VALUE_MAX];
+ int fd_count = 0;
struct pollfd ufds[4];
char *tmpdev;
char* debuggable;
+ char tmp[32];
+ int device_fd_init = 0;
+ int property_set_fd_init = 0;
+ int signal_fd_init = 0;
+ int keychord_fd_init = 0;
/* clear the umask */
umask(0);
@@ -582,149 +754,79 @@
parse_config_file(tmp);
action_for_each_trigger("early-init", action_add_queue_tail);
- drain_action_queue();
- INFO("device init\n");
- device_init();
-
- property_init();
-
- // only listen for keychords if ro.debuggable is true
- keychord_init();
-
- if (console[0]) {
- snprintf(tmp, sizeof(tmp), "/dev/%s", console);
- console_name = strdup(tmp);
- }
-
- fd = open(console_name, O_RDWR);
- if (fd >= 0)
- have_console = 1;
- close(fd);
-
- if( load_565rle_image(INIT_IMAGE_FILE) ) {
- fd = open("/dev/tty0", O_WRONLY);
- if (fd >= 0) {
- const char *msg;
- msg = "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n" // console is 40 cols x 30 lines
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- " A N D R O I D ";
- write(fd, msg, strlen(msg));
- close(fd);
- }
- }
-
- if (qemu[0])
- import_kernel_cmdline(1);
-
- if (!strcmp(bootmode,"factory"))
- property_set("ro.factorytest", "1");
- else if (!strcmp(bootmode,"factory2"))
- property_set("ro.factorytest", "2");
- else
- property_set("ro.factorytest", "0");
-
- property_set("ro.serialno", serialno[0] ? serialno : "");
- property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
- property_set("ro.baseband", baseband[0] ? baseband : "unknown");
- property_set("ro.carrier", carrier[0] ? carrier : "unknown");
- property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
-
- property_set("ro.hardware", hardware);
- snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
- property_set("ro.revision", tmp);
+ queue_builtin_action(device_init_action, "device_init");
+ queue_builtin_action(property_init_action, "property_init");
+ queue_builtin_action(keychord_init_action, "keychord_init");
+ queue_builtin_action(console_init_action, "console_init");
+ queue_builtin_action(set_init_properties_action, "set_init_properties");
/* execute all the boot actions to get us started */
action_for_each_trigger("init", action_add_queue_tail);
action_for_each_trigger("early-fs", action_add_queue_tail);
action_for_each_trigger("fs", action_add_queue_tail);
action_for_each_trigger("post-fs", action_add_queue_tail);
- drain_action_queue();
- /* read any property files on system or data and
- * fire up the property service. This must happen
- * after the ro.foo properties are set above so
- * that /data/local.prop cannot interfere with them.
- */
- start_property_service();
-
- signal_init();
-
- /* make sure we actually have all the pieces we need */
- if ((get_device_fd() < 0) ||
- (get_property_set_fd() < 0) ||
- (get_signal_fd() < 0)) {
- ERROR("init startup failure\n");
- return 1;
- }
+ queue_builtin_action(property_service_init_action, "property_service_init");
+ queue_builtin_action(signal_init_action, "signal_init");
+ queue_builtin_action(check_startup_action, "check_startup");
/* execute all the boot actions to get us started */
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);
- drain_action_queue();
/* run all property triggers based on current state of the properties */
- queue_all_property_triggers();
- drain_action_queue();
+ queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers");
- /* enable property triggers */
- property_triggers_enabled = 1;
-
- ufds[0].fd = get_device_fd();
- ufds[0].events = POLLIN;
- ufds[1].fd = get_property_set_fd();
- ufds[1].events = POLLIN;
- ufds[2].fd = get_signal_fd();
- ufds[2].events = POLLIN;
- fd_count = 3;
-
- if (get_keychord_fd() > 0) {
- ufds[3].fd = get_keychord_fd();
- ufds[3].events = POLLIN;
- fd_count++;
- } else {
- ufds[3].events = 0;
- ufds[3].revents = 0;
- }
#if BOOTCHART
- 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");
- }
+ queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif
for(;;) {
int nr, i, timeout = -1;
- for (i = 0; i < fd_count; i++)
- ufds[i].revents = 0;
-
- drain_action_queue();
+ execute_one_command();
restart_processes();
+ if (!device_fd_init && get_device_fd() > 0) {
+ ufds[fd_count].fd = get_device_fd();
+ ufds[fd_count].events = POLLIN;
+ ufds[fd_count].revents = 0;
+ fd_count++;
+ device_fd_init = 1;
+ }
+ if (!property_set_fd_init && get_property_set_fd() > 0) {
+ ufds[fd_count].fd = get_property_set_fd();
+ ufds[fd_count].events = POLLIN;
+ ufds[fd_count].revents = 0;
+ fd_count++;
+ property_set_fd_init = 1;
+ }
+ if (!signal_fd_init && get_signal_fd() > 0) {
+ ufds[fd_count].fd = get_signal_fd();
+ ufds[fd_count].events = POLLIN;
+ ufds[fd_count].revents = 0;
+ fd_count++;
+ signal_fd_init = 1;
+ }
+ if (!keychord_fd_init && get_keychord_fd() > 0) {
+ ufds[fd_count].fd = get_keychord_fd();
+ ufds[fd_count].events = POLLIN;
+ ufds[fd_count].revents = 0;
+ fd_count++;
+ keychord_fd_init = 1;
+ }
+
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
+ if (!action_queue_empty() || cur_command)
+ timeout = 0;
+
#if BOOTCHART
if (bootchart_count > 0) {
if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
@@ -735,22 +837,23 @@
}
}
#endif
+
nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;
- if (ufds[2].revents == POLLIN) {
- handle_signal();
- continue;
+ for (i = 0; i < fd_count; i++) {
+ if (ufds[i].revents == POLLIN) {
+ if (ufds[i].fd == get_device_fd())
+ handle_device_fd();
+ else if (ufds[i].fd == get_property_set_fd())
+ handle_property_set_fd();
+ else if (ufds[i].fd == get_keychord_fd())
+ handle_keychord();
+ else if (ufds[i].fd == get_signal_fd())
+ handle_signal();
+ }
}
-
- if (ufds[0].revents == POLLIN)
- handle_device_fd();
-
- if (ufds[1].revents == POLLIN)
- handle_property_set_fd();
- if (ufds[3].revents == POLLIN)
- handle_keychord();
}
return 0;