feat: extend kmain with globTypeGlobcatCommand and globDriverThread

This commit is contained in:
dualfroz committed 2026-09-06 12:22:05 +02:00
1 parent fbd54b7c31
commit 68907b39ec
1 file changed
+173
+173
View File
@@ -1542,6 +1542,179 @@ static void globTypeEchoSkipCommand(void)
injectKeyPress(scancodeMakeP);
injectKeyPress(scancodeMakeSlash);
injectKeyPress(scancodeMakeG);
injectKeyPress(scancodeMakeD);
injectKeyPress(scancodeMakeSlash);
injectKeyPress(scancodeCPressMake);
injectKeyPress(scancodeMakeDot);
injectKeyPress(scancodeMakeL);
injectKeyPress(scancodeMakeO);
injectKeyPress(scancodeMakeG);
injectKeyPress(scancodeMakeEnter);
}
static void globTypeGlobcatCommand(void)
{
injectKeyPress(scancodeMakeG);
injectKeyPress(scancodeMakeL);
injectKeyPress(scancodeMakeO);
injectKeyPress(scancodeMakeB);
injectKeyPress(scancodeCPressMake);
injectKeyPress(scancodeMakeA);
injectKeyPress(scancodeMakeT);
injectKeyPress(scancodeMakeSpace);
injectKeyPress(scancodeMakeSlash);
injectKeyPress(scancodeMakeT);
injectKeyPress(scancodeMakeM);
injectKeyPress(scancodeMakeP);
injectKeyPress(scancodeMakeSlash);
injectKeyPress(scancodeMakeG);
injectKeyPress(scancodeMakeD);
injectKeyPress(scancodeMakeSlash);
injectShiftedKeyPress(scancodeMakeEight);
injectKeyPress(scancodeMakeDot);
injectKeyPress(scancodeMakeT);
injectKeyPress(scancodeMakeX);
injectKeyPress(scancodeMakeT);
injectKeyPress(scancodeMakeEnter);
}
/* 15000ms clears envDriverThread's own total budget (12500 initial +
3*400 settle = 13700ms, above its own real spawn/run/reap time), the same
"next demo's initial delay clears the previous demo's total budget"
convention every driver thread above already establishes. Settle is
300ms per step, matching redirDriverThread's own choice for similarly
trivial commands (a single mkdir or a single short file write, none of
which ever sleeps or blocks on a timer) -- comfortable headroom to let
the shell finish running each FOREGROUND command before the next one's
keystrokes are typed into the same shared 32-byte console-reader ring
buffer (keyboard.c). */
#define globDriverInitialDelayMs 15000
#define globDriverStepSettleMs 300
/*
* Live ring-3 proof for shell.c's new wildcard glob expansion
* (shellExpandGlobs, shellGlobMatch/shellTokenHasGlob/shellSplitGlobToken):
* types four setup commands at the real interactive shell (mkdir, then
* three "echo X > /tmp/gd/NAME" writes -- two matching *.txt, one
* deliberately a *.log that must NOT match), then "globcat /tmp/gd/ *.txt".
* shell.c resolves that last argv token against the real tmpfs directory
* /tmp/gd (vfsChild/vfsNext, the exact traversal the `ls` builtin already
* uses) and replaces it with however many real paths matched BEFORE
* globcat.c (loaded on demand, like envprint/hcat/pipecat above) ever runs
* a single instruction -- so globcat.c's own argc/argv and each file's
* content are the actual proof: exactly 2 files (never 3 -- c.log must be
* filtered out by pattern, not just "everything in the directory"), each
* one's real resolved path and its own distinct content. The actual
* pass/fail proof is entirely globcat.c's own doing; this thread's only job
* is to type the five commands and give the scheduler real time between
* them.
*/
static void globDriverThread(void)
{
threadSleep(globDriverInitialDelayMs);
while (currentThread()->state == threadSleeping)
halt();
kprintf("[kbd] typing shell commands for the wildcard glob demo\n");
jobctlTypeFlushLine();
globTypeMkdirCommand();
threadSleep(globDriverStepSettleMs);
while (currentThread()->state == threadSleeping)
halt();
globTypeEchoACommand();
threadSleep(globDriverStepSettleMs);
while (currentThread()->state == threadSleeping)
halt();
globTypeEchoBCommand();
threadSleep(globDriverStepSettleMs);
while (currentThread()->state == threadSleeping)
halt();
globTypeEchoSkipCommand();
threadSleep(globDriverStepSettleMs);
while (currentThread()->state == threadSleeping)
halt();
globTypeGlobcatCommand();
threadSleep(globDriverStepSettleMs);
while (currentThread()->state == threadSleeping)
halt();
for (;;)
halt();
}
/* 19500ms clears globDriverThread's own total budget (15000 initial +
5*300 settle = 16500ms, plus the real time globcat.c itself needs to
spawn/run/read two files/print/exit after that last keystroke) -- the
same "next demo's initial delay clears the previous demo's total budget
with margin" convention every driver thread above establishes. A single
settle step is enough -- see the file comment on lsDriverThread below
for why this demo types only ONE command, unlike every prior driver
thread's multi-command setup sequence: tools/ci-test.sh's QEMU timeout
is a fixed 25 REAL (host wall-clock) seconds shared by the entire boot,
and this is already the last of well over a dozen shell-driven demos
stacked at increasing absolute timestamps in that same fixed window, so
minimizing this demo's own keystroke count directly buys back margin
for the whole chain instead of spending it. */
#define lsDriverInitialDelayMs 19500
#define lsDriverStepSettleMs 300
static void lsTypeLongListCommand(void)
{
injectKeyPress(scancodeMakeL);
injectKeyPress(scancodeMakeS);
injectKeyPress(scancodeMakeSpace);
injectKeyPress(scancodeMakeHyphen);
injectKeyPress(scancodeMakeL);
injectKeyPress(scancodeMakeSpace);
injectKeyPress(scancodeMakeSlash);
injectKeyPress(scancodeMakeM);
injectKeyPress(scancodeMakeN);
injectKeyPress(scancodeMakeT);
injectKeyPress(scancodeMakeSlash);
injectKeyPress(scancodeMakeT);
injectKeyPress(scancodeMakeI);
injectKeyPress(scancodeMakeM);
injectKeyPress(scancodeMakeE);
injectKeyPress(scancodeMakeT);
injectKeyPress(scancodeMakeE);
injectKeyPress(scancodeMakeS);
injectKeyPress(scancodeMakeT);
injectKeyPress(scancodeMakeEnter);
}
/*
* Live proof for shell.c's new generalized `ls`/`ls -l` (listDir/
* printLsEntry): types `ls -l /mnt/timetest` at the real interactive
* shell. `/mnt/timetest` is deliberately NOT created by this demo --
* timetest.c (FALA 39, boot-time synchronous, long finished by the time
* any shell-driven demo runs) already left it behind with two real files
* (data.txt, and alias.txt, a hardlink sharing the same inode/mtime) once
* `timetest: PASS` prints, so this demo needs exactly ONE typed command
* instead of the usual "mkdir + write setup, then the command under test"
* shape every earlier shell demo used -- both a deliberate budget saving
* (see lsDriverInitialDelayMs's own comment) and, incidentally, a second
* independent proof that `ls -l`'s real stat data (size, mtime) matches
* what timetest.c's own syscall-level userStat already established for
* the exact same on-disk inode, through a completely different code path
* (the interactive shell builtin instead of a ring-3 program's syscalls).
* `/mnt`, not `/tmp`, is the whole point -- the OLD `ls` only ever
* understood the tmpfs VfsNode tree via vfsLookup/vfsChild/vfsNext, so any
* `/mnt` directory silently reported "no such path" no matter what it
* actually held (fstest.c/linktest.c could only ever prove SFS directory
* listing through a raw userGetdents syscall, never through this
* builtin). The needles tools/ci-test.sh checks for are the deterministic
* type+size+name prefix of each `-l` output line ("f <N> data.txt " and
* "f <N> alias.txt ", both files' real on-disk size) plus a "20" year-
* prefix right after one of them, proving a real mtime got formatted and
* printed (sfs.h's on-disk timestamp, rtc.c's new rtcCivilFromEpoch)
* rather than silently falling back to the "no timestamp" dash this same
* code path prints for tmpfs/dev entries.
*/
}
void kmain(uint32 magic, uint64 multibootInfo)