diff --git a/projects/ArchR/packages/archr/system.d/archr-memory-manager.service b/projects/ArchR/packages/archr/system.d/archr-memory-manager.service index e8a38f66e2..b526396ab4 100644 --- a/projects/ArchR/packages/archr/system.d/archr-memory-manager.service +++ b/projects/ArchR/packages/archr/system.d/archr-memory-manager.service @@ -1,7 +1,9 @@ [Unit] Description=ArchR Memory Manager -After=local-fs.target -DefaultDependencies=no +# Run AFTER /storage is mountable so we can read /storage/.config/swap.conf +# for user overrides. RequiresMountsFor pulls in the mount automatically. +After=local-fs.target archr-automount.service +RequiresMountsFor=/storage Conflicts=shutdown.target Before=shutdown.target @@ -14,4 +16,9 @@ ExecStop=/usr/bin/archr-memory-manager --stop RemainAfterExit=yes [Install] -WantedBy=basic.target +# Was WantedBy=basic.target, which put the ~3.9s modprobe zram + udev wait +# + sysctl tuning loop on the critical path before sockets.target → +# sysinit.target. Moving to multi-user.target keeps swap+KSM+VM tuning +# functional (it still happens before EmulationStation starts) but +# unblocks sysinit/basic for the rest of the boot. +WantedBy=multi-user.target diff --git a/projects/ArchR/packages/sysutils/autostart/sources/autostart b/projects/ArchR/packages/sysutils/autostart/sources/autostart index b25093b939..9d6e5c0479 100755 --- a/projects/ArchR/packages/sysutils/autostart/sources/autostart +++ b/projects/ArchR/packages/sysutils/autostart/sources/autostart @@ -50,36 +50,29 @@ if [ -d /sys/class/pwm/pwmchip0 ]; then echo 0 > /sys/class/pwm/pwmchip0/pwm0/enable 2>/dev/null fi -### Load platform specific quirks -if [ -d "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}" ] -then - log "Run ${HW_DEVICE} quirks." - tocon "Applying ${HW_DEVICE} quirks..." - for script in "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}"/* - do - log "Run ${script}" - trace_step "platform-quirk:${script}" - if [ -f "${script}" ] - then - "${script}" 2>&1 >>${BOOTLOG} - fi - done -fi +### Load platform + device quirks in parallel. Every quirk writes to its +### own /storage/.config/profile.d/NNN-name file or to a hardware sysfs +### path — they don't share state, so running them concurrently is safe +### and trims several seconds off boot (most quirks are sub-second cats). +### Each quirk is logged with its end-tag so a failure is still +### attributable in /var/log/boot.log; the trace_step marker for slow +### debugging picks the LAST-launched script (good enough — if a quirk +### hangs we want to know what's still running, not the entry order). +QUIRK_DIRS="" +[ -d "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}" ] && QUIRK_DIRS+=" /usr/lib/autostart/quirks/platforms/${HW_DEVICE}" +[ -d "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}" ] && QUIRK_DIRS+=" /usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}" -### Load device specific quirks -if [ -d "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}" ] -then - log "Run ${QUIRK_DEVICE} quirks." - tocon "Applying ${QUIRK_DEVICE} quirks..." - for script in "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}"/* - do - log "Run ${script}" - trace_step "device-quirk:${script}" - if [ -f "${script}" ] - then - "${script}" 2>&1 >>${BOOTLOG} - fi +if [ -n "${QUIRK_DIRS}" ]; then + tocon "Applying ${HW_DEVICE} / ${QUIRK_DEVICE} quirks..." + for QDIR in ${QUIRK_DIRS}; do + for script in "${QDIR}"/*; do + [ -f "${script}" ] || continue + log "Run ${script}" + trace_step "quirk:${script}" + ( "${script}" 2>&1 >>${BOOTLOG}; log "Done ${script}" ) & + done done + wait fi ### Start the automount service diff --git a/projects/ArchR/packages/sysutils/systemd/package.mk b/projects/ArchR/packages/sysutils/systemd/package.mk index 5dd048a246..74a1d829b8 100644 --- a/projects/ArchR/packages/sysutils/systemd/package.mk +++ b/projects/ArchR/packages/sysutils/systemd/package.mk @@ -154,8 +154,15 @@ post_makeinstall_target() { safe_remove ${INSTALL}/usr/lib/systemd/system/systemd-journald-audit.socket - # adjust systemd-hwdb-update (we have read-only /etc). - sed '/^ConditionNeedsUpdate=.*$/d' -i ${INSTALL}/usr/lib/systemd/system/systemd-hwdb-update.service + # Pre-build hwdb.bin at image creation so systemd-hwdb-update.service + # doesn't have to rebuild it on every boot (was costing ~4.4s in + # systemd-analyze blame). The file format is arch-independent so the + # host's systemd-hwdb is safe to use. The override.conf in + # system.d/systemd-hwdb-update.service.d makes the service a no-op at + # runtime; this step ensures the binary db is present for udev. + if command -v systemd-hwdb >/dev/null; then + systemd-hwdb --usr --root=${INSTALL} update || true + fi # remove nspawn safe_remove ${INSTALL}/usr/bin/systemd-nspawn diff --git a/projects/ArchR/packages/sysutils/systemd/system.d/systemd-hwdb-update.service.d/override.conf b/projects/ArchR/packages/sysutils/systemd/system.d/systemd-hwdb-update.service.d/override.conf new file mode 100644 index 0000000000..1aa756d7e4 --- /dev/null +++ b/projects/ArchR/packages/sysutils/systemd/system.d/systemd-hwdb-update.service.d/override.conf @@ -0,0 +1,16 @@ +[Unit] +# /usr is read-only squashfs/ext2 in ArchR — the hwdb source files never +# change between boots, so rebuilding hwdb.bin at every boot was costing +# ~4s on RK3326 (systemd-analyze blame: 4.417s) and showed up in the +# critical chain via sysinit.target. +# +# We rebuild hwdb.bin at image creation (see systemd post_makeinstall) and +# ship it with the image. At runtime, skip the rebuild unconditionally by +# ConditionPathExists pointing at a sentinel path that never exists. +ConditionPathExists=/run/systemd/never-create-this + +[Service] +# Defensive: if the condition somehow doesn't kick in, exit immediately +# so we still avoid the 4s rebuild. +ExecStart= +ExecStart=/bin/true diff --git a/projects/ArchR/packages/sysutils/systemd/system.d/systemd-resolved.service.d/override.conf b/projects/ArchR/packages/sysutils/systemd/system.d/systemd-resolved.service.d/override.conf index 68719b53e8..23b3fb20c1 100644 --- a/projects/ArchR/packages/sysutils/systemd/system.d/systemd-resolved.service.d/override.conf +++ b/projects/ArchR/packages/sysutils/systemd/system.d/systemd-resolved.service.d/override.conf @@ -1,3 +1,13 @@ +[Unit] +# systemd-resolved was sitting in the boot critical chain via +# nss-lookup.target → basic.target → sysinit.target, costing ~4.3s in +# blame. None of ArchR's boot-critical services actually need DNS +# (EmulationStation, sway, automount). Drop the implicit pull so +# resolved starts in the background while the UI comes up; DNS is ready +# by the time the user actually opens a network app. +Wants= +Before=systemd-user-sessions.service shutdown.target + [Service] # Relax sandboxing to prevent race conditions on boot with OverlayFS # Fixes error: NAMESPACE "Failed to set up mount namespacing" which can occur based on overlayfs setup speed