Skip to content

Commit e4db6cd

Browse files
committed
perf(zaparoo): reduce launcher startup contention
1 parent 7a05c05 commit e4db6cd

3 files changed

Lines changed: 140 additions & 71 deletions

File tree

scheduler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "scheduler.h"
22
#include <stdio.h>
3+
#include <unistd.h>
34
#include "libco.h"
45
#include "menu.h"
56
#include "user_io.h"
@@ -86,6 +87,8 @@ void scheduler_run(void)
8687
for (;;)
8788
{
8889
scheduler_schedule();
90+
if (alt_launcher_scheduler_sleep_enabled())
91+
usleep(100);
8992
}
9093

9194
co_delete(co_ui);

support/zaparoo/alt_launcher.cpp

Lines changed: 136 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ uint16_t alt_launcher_fb_terminal_key(uint32_t mask, bool osd_button)
6868
static pid_t s_pid = 0;
6969
static int s_crash_count = 0;
7070
static unsigned long s_respawn_timer = 0;
71+
static unsigned long s_tty_deadline = 0;
7172
static unsigned long s_native_status_timer = 0;
72-
static unsigned long s_native_fb_mode_timer = 0;
73+
static unsigned long s_native_crt_finish_timer = 0;
7374
static bool s_gave_up = false;
7475
static bool s_init_pending = false;
7576
static bool s_native_crt = false;
@@ -81,6 +82,8 @@ static const char s_tty_path[] = "/dev/tty2";
8182
static const char s_fb_mode_path[] = "/sys/module/MiSTer_fb/parameters/mode";
8283
static const char s_crt_state_file[] = "zaparoo_launcher_crt.bin";
8384
static const char s_offsets_file[] = "zaparoo_video_offsets.bin";
85+
static char s_saved_fb_mode[64];
86+
static bool s_saved_fb_mode_valid = false;
8487

8588
static int8_t s_h_offset = 0;
8689
static int8_t s_v_offset = 0;
@@ -134,9 +137,48 @@ static void set_launcher_fb_mode(int fmt, int rb, int width, int height, int str
134137
printf("alt_launcher: fb mode set to %dx%d fmt=%d stride=%d\n", width, height, fmt, stride);
135138
}
136139

137-
static void set_native_crt_fb_mode(bool log = true)
140+
static void save_current_fb_mode(void)
138141
{
139-
set_launcher_fb_mode(8888, 1, 320, 240, 1280, log);
142+
if (s_saved_fb_mode_valid)
143+
return;
144+
145+
FILE *fp = fopen(s_fb_mode_path, "rt");
146+
if (!fp)
147+
{
148+
printf("alt_launcher: unable to read fb mode: %s\n", strerror(errno));
149+
return;
150+
}
151+
152+
if (fgets(s_saved_fb_mode, sizeof(s_saved_fb_mode), fp))
153+
{
154+
size_t len = strlen(s_saved_fb_mode);
155+
while (len && (s_saved_fb_mode[len - 1] == '\n' || s_saved_fb_mode[len - 1] == '\r'))
156+
s_saved_fb_mode[--len] = 0;
157+
s_saved_fb_mode_valid = len != 0;
158+
if (s_saved_fb_mode_valid)
159+
printf("alt_launcher: saved fb mode '%s'\n", s_saved_fb_mode);
160+
}
161+
fclose(fp);
162+
}
163+
164+
static void restore_saved_fb_mode(void)
165+
{
166+
if (!s_saved_fb_mode_valid)
167+
{
168+
set_launcher_fb_mode(8888, 1, 960, 720, 3840);
169+
return;
170+
}
171+
172+
FILE *fp = fopen(s_fb_mode_path, "wt");
173+
if (!fp)
174+
{
175+
printf("alt_launcher: unable to restore fb mode: %s\n", strerror(errno));
176+
return;
177+
}
178+
179+
fprintf(fp, "%s\n", s_saved_fb_mode);
180+
fclose(fp);
181+
printf("alt_launcher: restored fb mode '%s'\n", s_saved_fb_mode);
140182
}
141183

142184
static void blank_native_crt_fb(void)
@@ -227,41 +269,33 @@ static void disable_native_crt_path(void)
227269
user_io_status_set("[9]", 0);
228270
video_fb_enable(0);
229271
set_vga_fb(0);
230-
set_launcher_fb_mode(8888, 1, 960, 720, 3840);
272+
restore_saved_fb_mode();
273+
s_tty_deadline = 0;
231274
s_native_status_timer = 0;
232-
s_native_fb_mode_timer = 0;
275+
s_native_crt_finish_timer = 0;
233276
}
234277

235-
static void enable_native_crt_path(void)
278+
static void prepare_native_crt_path(void)
236279
{
237280
set_vga_fb(0);
238281
video_fb_enable(0);
282+
save_current_fb_mode();
283+
s_native_crt_finish_timer = GetTimer(1);
284+
if (!s_native_crt_finish_timer) s_native_crt_finish_timer = 1;
285+
}
239286

240-
// Double-write with a settle window so the kernel module's 320x240 layout
241-
// is live before status[9] flips. Without this, the frontend renders for
242-
// up to a second under stale dims (the post-fork retry timer used to be
243-
// what eventually fixed the picture).
244-
set_native_crt_fb_mode(false);
245-
usleep(100000);
246-
set_native_crt_fb_mode();
287+
static void finish_native_crt_path(void)
288+
{
289+
// Main_MiSTer does not program the launcher framebuffer mode. The
290+
// frontend owns its linuxfb `vmode`; this side only blanks the native DDR
291+
// scan-out buffer before status[9] routes the FPGA to it.
292+
s_native_crt_finish_timer = 0;
247293

248294
blank_native_crt_fb();
249295

250296
user_io_status_set("[9]", 1);
251297
s_native_status_timer = GetTimer(500);
252298
if (!s_native_status_timer) s_native_status_timer = 1;
253-
s_native_fb_mode_timer = GetTimer(1000);
254-
if (!s_native_fb_mode_timer) s_native_fb_mode_timer = 1;
255-
}
256-
257-
static void wait_launcher_tty_ready(pid_t pid)
258-
{
259-
for (int i = 0; i < 100; i++)
260-
{
261-
if (launcher_tty_ready(pid))
262-
return;
263-
usleep(10000);
264-
}
265299
}
266300

267301
static void return_to_normal_mode(void)
@@ -282,6 +316,9 @@ static void reset_launcher_state(void)
282316
{
283317
s_pid = 0;
284318
s_respawn_timer = 0;
319+
s_tty_deadline = 0;
320+
s_native_status_timer = 0;
321+
s_native_crt_finish_timer = 0;
285322
s_crash_count = 0;
286323
s_gave_up = false;
287324
s_init_pending = false;
@@ -337,34 +374,71 @@ static void release_launcher_video(void)
337374
}
338375
}
339376

377+
static void exec_launcher_child(const char *path)
378+
{
379+
setenv("LC_ALL", "en_US.UTF-8", 1);
380+
setenv("HOME", "/root", 1);
381+
382+
cpu_set_t set;
383+
CPU_ZERO(&set);
384+
CPU_SET(0, &set);
385+
sched_setaffinity(0, sizeof(set), &set);
386+
387+
setsid();
388+
389+
int tty_fd = open(s_tty_path, O_RDWR);
390+
if (tty_fd >= 0)
391+
{
392+
ioctl(tty_fd, TIOCSCTTY, 0);
393+
dup2(tty_fd, STDIN_FILENO);
394+
dup2(tty_fd, STDOUT_FILENO);
395+
dup2(tty_fd, STDERR_FILENO);
396+
if (tty_fd > STDERR_FILENO)
397+
close(tty_fd);
398+
}
399+
400+
static const char clear[] = "\033[0m\033[?25l\033[37m\033[40m\033[2J\033[H";
401+
if (write(STDOUT_FILENO, clear, sizeof(clear) - 1) < 0) {}
402+
403+
if (s_native_crt)
404+
execl(path, path, "--crt", NULL);
405+
else
406+
execl(path, path, NULL);
407+
_exit(1);
408+
}
409+
410+
static void finalize_spawn(void)
411+
{
412+
s_tty_deadline = 0;
413+
video_chvt(s_vt);
414+
if (!s_native_crt)
415+
video_fb_enable(1);
416+
else
417+
{
418+
input_switch(0);
419+
user_io_status_set("[9]", 1);
420+
}
421+
422+
// The frontend grabs input as soon as it starts. If the OSD is still
423+
// up (e.g. user toggled CRT mode or hit Reboot from System Settings),
424+
// it would trap input with no way to dismiss it — drop it now.
425+
if (menu_present()) MenuHide();
426+
}
427+
340428
static void spawn(void)
341429
{
342430
char path[2100];
343431
strncpy(path, getFullPath(s_launcher_path), sizeof(path) - 1);
344432
path[sizeof(path) - 1] = '\0';
345433

346-
static const char cmd[] =
347-
"#!/bin/bash\n"
348-
"export LC_ALL=en_US.UTF-8\n"
349-
"export HOME=/root\n"
350-
"printf '\\033[0m\\033[?25l\\033[37m\\033[40m\\033[2J\\033[H'\n"
351-
"if [ \"$ALT_LAUNCHER_CRT\" = \"1\" ]; then\n"
352-
" exec \"$ALT_LAUNCHER_PATH\" --crt\n"
353-
"fi\n"
354-
"exec \"$ALT_LAUNCHER_PATH\"\n";
355-
356-
unlink("/tmp/alt_launcher");
357-
if (!FileSave("/tmp/alt_launcher", (void*)cmd, strlen(cmd)))
358-
return;
359-
360434
user_io_osd_key_enable(0);
361435
clear_launcher_tty();
362436

363437
printf("alt_launcher: native_crt=%d\n", s_native_crt);
364438
if (s_native_crt)
365439
{
366-
enable_native_crt_path();
367-
printf("alt_launcher: native CRT path enabled\n");
440+
prepare_native_crt_path();
441+
printf("alt_launcher: native CRT path prepared\n");
368442
}
369443
else
370444
{
@@ -384,39 +458,23 @@ static void spawn(void)
384458
printf("alt_launcher: spawned pid=%d path=%s\n", s_pid, path);
385459
if (!s_pid)
386460
{
387-
setenv("ALT_LAUNCHER_PATH", path, 1);
388-
setenv("ALT_LAUNCHER_CRT", s_native_crt ? "1" : "0", 1);
389-
cpu_set_t set;
390-
CPU_ZERO(&set);
391-
CPU_SET(0, &set);
392-
sched_setaffinity(0, sizeof(set), &set);
393-
setsid();
394-
execl("/sbin/agetty", "/sbin/agetty", "-a", "root", "-l",
395-
"/tmp/alt_launcher", "-i", "--nohostname", "-L", s_tty, "linux", NULL);
396-
_exit(1);
397-
}
398-
399-
wait_launcher_tty_ready(s_pid);
400-
video_chvt(s_vt);
401-
if (!s_native_crt)
402-
video_fb_enable(1);
403-
else
404-
{
405-
input_switch(0);
406-
user_io_status_set("[9]", 1);
461+
exec_launcher_child(path);
407462
}
408463

409-
// The frontend grabs input as soon as it starts. If the OSD is still
410-
// up (e.g. user toggled CRT mode or hit Reboot from System Settings),
411-
// it would trap input with no way to dismiss it — drop it now.
412-
if (menu_present()) MenuHide();
464+
s_tty_deadline = GetTimer(1000);
465+
if (!s_tty_deadline) s_tty_deadline = 1;
413466
}
414467

415468
bool alt_launcher_active(void)
416469
{
417470
return s_pid != 0;
418471
}
419472

473+
bool alt_launcher_scheduler_sleep_enabled(void)
474+
{
475+
return s_pid || s_init_pending || s_respawn_timer || s_tty_deadline || s_native_crt_finish_timer;
476+
}
477+
420478
bool alt_launcher_native_crt(void)
421479
{
422480
return s_native_crt && s_pid != 0;
@@ -469,6 +527,7 @@ void alt_launcher_init(bool native_crt)
469527
return;
470528
s_crash_count = 0;
471529
s_respawn_timer = 0;
530+
s_tty_deadline = 0;
472531
s_native_crt = native_crt;
473532
s_init_pending = true;
474533
}
@@ -486,6 +545,7 @@ void alt_launcher_prepare_for_script(void)
486545
wait_launcher_stopped(pid);
487546
user_io_osd_key_enable(1);
488547
s_respawn_timer = 0;
548+
s_tty_deadline = 0;
489549
s_crash_count = 0;
490550
s_init_pending = false;
491551
s_gave_up = false;
@@ -514,23 +574,24 @@ void alt_launcher_poll(void)
514574
{
515575
if (s_pid)
516576
{
577+
if (s_native_crt && s_native_crt_finish_timer && CheckTimer(s_native_crt_finish_timer))
578+
{
579+
finish_native_crt_path();
580+
printf("alt_launcher: native CRT path enabled\n");
581+
}
582+
517583
if (s_native_crt && s_native_status_timer && CheckTimer(s_native_status_timer))
518584
{
519585
user_io_status_set("[9]", 1);
520586
s_native_status_timer = GetTimer(500);
521587
if (!s_native_status_timer) s_native_status_timer = 1;
522588
}
523589

524-
if (s_native_crt && s_native_fb_mode_timer && CheckTimer(s_native_fb_mode_timer))
525-
{
526-
set_native_crt_fb_mode();
527-
s_native_fb_mode_timer = 0;
528-
}
529-
530590
int status;
531591
if (waitpid(s_pid, &status, WNOHANG) == s_pid)
532592
{
533593
s_pid = 0;
594+
s_tty_deadline = 0;
534595
user_io_osd_key_enable(1);
535596
bool exited = WIFEXITED(status);
536597
int exit_status = exited ? WEXITSTATUS(status) : 0;
@@ -565,7 +626,11 @@ void alt_launcher_poll(void)
565626
s_crash_count = 0;
566627
s_respawn_timer = GetTimer(1000);
567628
if (!s_respawn_timer) s_respawn_timer = 1;
629+
return;
568630
}
631+
632+
if (s_tty_deadline && !s_native_crt_finish_timer && (launcher_tty_ready(s_pid) || CheckTimer(s_tty_deadline)))
633+
finalize_spawn();
569634
return;
570635
}
571636

support/zaparoo/alt_launcher.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ void alt_launcher_resume_after_script(void);
1313
bool alt_launcher_native_crt(void);
1414
bool alt_launcher_active(void);
1515
bool alt_launcher_configured(void);
16+
bool alt_launcher_scheduler_sleep_enabled(void);
1617

1718
// Display centering: signed offsets clamped to -8..+7. Setters update the
1819
// in-memory cache, persist to the config dir, and push to the FPGA via

0 commit comments

Comments
 (0)