ueventd: parallelize uevent handling
fork() subprocesses to handle uevents in parallel.
This reduces coldboot time on bullhead from ~446ms to ~230ms.
This reduces coldboot time on sailfish from ~690ms to ~360ms.
This reduces coldboot time on ryu from ~187ms to ~122ms.
Bug: 33785894
Test: boot bullhead x40, observe no major differences in /dev and /sys
Test: boot sailfish x40, observe no major differences in /dev and /sys
Test: boot ryu x40, observe no major differences in /dev and /sys
Test: boottime tests on bullhead and sailfish
Test: init unit tests
Change-Id: Ie2f63e000b8af78d187477d31fe109f20304d749
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index 1471aeb..844c605 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <sys/sendfile.h>
+#include <sys/wait.h>
#include <unistd.h>
#include <string>
@@ -103,14 +104,29 @@
if (uevent.subsystem != "firmware" || uevent.action != "add") return;
// Loading the firmware in a child means we can do that in parallel...
- // (We ignore SIGCHLD rather than wait for our children.)
+ // We double fork instead of waiting for these processes.
pid_t pid = fork();
- if (pid == 0) {
- Timer t;
- ProcessFirmwareEvent(uevent);
- LOG(INFO) << "loading " << uevent.path << " took " << t;
- _exit(EXIT_SUCCESS);
- } else if (pid == -1) {
+ if (pid == -1) {
PLOG(ERROR) << "could not fork to process firmware event for " << uevent.firmware;
+ return;
}
+
+ if (pid == 0) {
+ pid = fork();
+ if (pid == -1) {
+ PLOG(ERROR) << "could not fork a sceond time to process firmware event for "
+ << uevent.firmware;
+ _exit(EXIT_FAILURE);
+ }
+ if (pid == 0) {
+ Timer t;
+ ProcessFirmwareEvent(uevent);
+ LOG(INFO) << "loading " << uevent.path << " took " << t;
+ _exit(EXIT_SUCCESS);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ waitpid(pid, nullptr, 0);
}