feat: extend kmain with stderrDriverThread
This commit is contained in:
1 parent
04d722667e
commit
d621db9147
1 file changed
+173
+173
@@ -1196,6 +1196,179 @@ static void hereStringPipelineDriverThread(void)
|
||||
* "stderrwriter 2>> /tmp/stderr.txt" (append, same path) leaves a real
|
||||
* tmpfs file holding two back-to-back copies of stderrwriter.c's own
|
||||
* payload; "stderrreader < /tmp/stderr.txt" then reads that file back
|
||||
* through a REAL redirected stdin and compares it byte-for-byte against
|
||||
* exactly that doubled payload. The actual pass/fail proof is entirely
|
||||
* stderrreader.c's own doing (its "payload-ok" needle only prints on an
|
||||
* exact match) -- this thread's only job is to type the three commands and
|
||||
* give the scheduler real time between them.
|
||||
*/
|
||||
static void stderrDriverThread(void)
|
||||
{
|
||||
threadSleep(stderrDriverInitialDelayMs);
|
||||
while (currentThread()->state == threadSleeping)
|
||||
halt();
|
||||
|
||||
kprintf("[kbd] typing shell commands for the stderr redirection demo\n");
|
||||
jobctlTypeFlushLine();
|
||||
|
||||
stderrTypeWriteTruncateCommand();
|
||||
threadSleep(stderrDriverStepSettleMs);
|
||||
while (currentThread()->state == threadSleeping)
|
||||
halt();
|
||||
|
||||
stderrTypeWriteAppendCommand();
|
||||
threadSleep(stderrDriverStepSettleMs);
|
||||
while (currentThread()->state == threadSleeping)
|
||||
halt();
|
||||
|
||||
stderrTypeReadCommand();
|
||||
threadSleep(stderrDriverStepSettleMs);
|
||||
while (currentThread()->state == threadSleeping)
|
||||
halt();
|
||||
|
||||
for (;;)
|
||||
halt();
|
||||
}
|
||||
|
||||
/* 10700ms gives hereStringPipelineDriverThread's own total budget
|
||||
(9000+500=9500ms, above its own real hcat/hsink spawn/run/reap time) a
|
||||
comfortable margin before this thread ever touches the same shared
|
||||
keyboard buffer, the same "next demo's initial delay clears the previous
|
||||
demo's total typing budget" convention every driver thread above already
|
||||
established. Settle is 600ms (slightly more than pipelineDriverThread's
|
||||
own 500ms for a 2-stage pipe) since this demo's pipe has one more real
|
||||
process (pipesrc, pipecat, AND pipesink) to spawn, run, and reap before
|
||||
the final needle can print. */
|
||||
#define threeStagePipelineDriverInitialDelayMs 10700
|
||||
#define threeStagePipelineDriverSettleMs 600
|
||||
|
||||
static void threeStagePipelineTypeCommand(void)
|
||||
{
|
||||
injectKeyPress(scancodeMakeP);
|
||||
injectKeyPress(scancodeMakeI);
|
||||
injectKeyPress(scancodeMakeP);
|
||||
injectKeyPress(scancodeMakeE);
|
||||
injectKeyPress(scancodeMakeS);
|
||||
injectKeyPress(scancodeMakeR);
|
||||
injectKeyPress(scancodeCPressMake);
|
||||
injectKeyPress(scancodeMakeSpace);
|
||||
injectShiftedKeyPress(scancodeMakeBackslash);
|
||||
injectKeyPress(scancodeMakeSpace);
|
||||
injectKeyPress(scancodeMakeP);
|
||||
injectKeyPress(scancodeMakeI);
|
||||
injectKeyPress(scancodeMakeP);
|
||||
injectKeyPress(scancodeMakeE);
|
||||
injectKeyPress(scancodeCPressMake);
|
||||
injectKeyPress(scancodeMakeA);
|
||||
injectKeyPress(scancodeMakeT);
|
||||
injectKeyPress(scancodeMakeSpace);
|
||||
injectShiftedKeyPress(scancodeMakeBackslash);
|
||||
injectKeyPress(scancodeMakeSpace);
|
||||
injectKeyPress(scancodeMakeP);
|
||||
injectKeyPress(scancodeMakeI);
|
||||
injectKeyPress(scancodeMakeP);
|
||||
injectKeyPress(scancodeMakeE);
|
||||
injectKeyPress(scancodeMakeS);
|
||||
injectKeyPress(scancodeMakeI);
|
||||
injectKeyPress(scancodeMakeN);
|
||||
injectKeyPress(scancodeMakeK);
|
||||
injectKeyPress(scancodeMakeEnter);
|
||||
}
|
||||
|
||||
/*
|
||||
* The live ring-3 proof for shell.c's new REAL N-stage pipeline
|
||||
* (runPipelineStages/jobctlWaitPipelineStages) going past two stages: types
|
||||
* "pipesrc | pipecat | pipesink" at the real interactive shell through the
|
||||
* same injected-keystroke mechanism every driver thread above already
|
||||
* uses, well after hereStringPipelineDriverThread's own total budget has
|
||||
* finished with the shell's shared line buffer.
|
||||
*
|
||||
* pipesrc.c and pipesink.c are reused completely unchanged from the
|
||||
* two-stage pipeline demo (FALA 29) -- their own narration ("wrote
|
||||
* payload", "blocking on read, waiting for pipesrc", "payload-ok") is still
|
||||
* literally true here, just relayed through one more real process instead
|
||||
* of being directly adjacent. The new thing this demo actually proves is
|
||||
* user/pipecat.c in the middle: jobctlSpawnPiped bakes a real pipe into
|
||||
* BOTH its fd 0 (from pipesrc's pipe) and its fd 1 (to pipesink's pipe)
|
||||
* before it ever runs a single instruction -- the first process in this
|
||||
* kernel with two DIFFERENT real inter-process pipes on its stdio at once
|
||||
* (hcat.c's own simultaneous piped-stdin-and-stdout, FALA 34, had a
|
||||
* shell-fed here-string on the stdin side, never a second real pipe). The
|
||||
* actual pass/fail proof is still entirely pipesink.c's own doing (its
|
||||
* "payload-ok" needle only prints on an exact byte-for-byte match of
|
||||
* whatever pipesrc originally wrote) -- this thread's only job is to type
|
||||
* the command and give all three spawned processes (none of which ever
|
||||
* sleeps or waits on a real timer) a comfortable amount of real scheduled
|
||||
* time to run to completion.
|
||||
*/
|
||||
static void threeStagePipelineDriverThread(void)
|
||||
{
|
||||
threadSleep(threeStagePipelineDriverInitialDelayMs);
|
||||
while (currentThread()->state == threadSleeping)
|
||||
halt();
|
||||
|
||||
kprintf("[kbd] typing shell command for the three-stage pipeline demo\n");
|
||||
jobctlTypeFlushLine();
|
||||
threeStagePipelineTypeCommand();
|
||||
|
||||
threadSleep(threeStagePipelineDriverSettleMs);
|
||||
while (currentThread()->state == threadSleeping)
|
||||
halt();
|
||||
|
||||
for (;;)
|
||||
halt();
|
||||
}
|
||||
|
||||
/* '=' (sysGetEnv/sysSetEnv's own operator, shell.c's `export N=V`
|
||||
builtin), 'y'/'Y', and 'v'/'V' are the only three make codes no earlier
|
||||
driver thread above ever needed -- every other letter "export",
|
||||
"GREETING", "envprint", and "env" use (e,x,p,o,r,t,g,i,n,f,s,b) was
|
||||
already defined by an earlier block. Cross-checked against
|
||||
keyboard.c's own scancodeLower/scancodeUpper tables the same way every
|
||||
block above documents for its own new codes. */
|
||||
#define scancodeMakeEquals 0x0D
|
||||
#define scancodeMakeY 0x15
|
||||
#define scancodeMakeV 0x2F
|
||||
|
||||
static void envTypeExportCommand(void)
|
||||
{
|
||||
injectKeyPress(scancodeMakeE);
|
||||
injectKeyPress(scancodeMakeX);
|
||||
injectKeyPress(scancodeMakeP);
|
||||
injectKeyPress(scancodeMakeO);
|
||||
injectKeyPress(scancodeMakeR);
|
||||
injectKeyPress(scancodeMakeT);
|
||||
injectKeyPress(scancodeMakeSpace);
|
||||
injectShiftedKeyPress(scancodeMakeG);
|
||||
injectShiftedKeyPress(scancodeMakeR);
|
||||
injectShiftedKeyPress(scancodeMakeE);
|
||||
injectShiftedKeyPress(scancodeMakeE);
|
||||
injectShiftedKeyPress(scancodeMakeT);
|
||||
injectShiftedKeyPress(scancodeMakeI);
|
||||
injectShiftedKeyPress(scancodeMakeN);
|
||||
injectShiftedKeyPress(scancodeMakeG);
|
||||
injectKeyPress(scancodeMakeEquals);
|
||||
injectKeyPress(scancodeMakeF);
|
||||
injectKeyPress(scancodeMakeR);
|
||||
injectKeyPress(scancodeMakeO);
|
||||
injectKeyPress(scancodeMakeS);
|
||||
injectKeyPress(scancodeMakeT);
|
||||
injectKeyPress(scancodeMakeB);
|
||||
injectKeyPress(scancodeMakeY);
|
||||
injectKeyPress(scancodeMakeT);
|
||||
injectKeyPress(scancodeMakeE);
|
||||
injectKeyPress(scancodeMakeEnter);
|
||||
}
|
||||
|
||||
static void envTypeEnvprintCommand(void)
|
||||
{
|
||||
injectKeyPress(scancodeMakeE);
|
||||
injectKeyPress(scancodeMakeN);
|
||||
injectKeyPress(scancodeMakeV);
|
||||
injectKeyPress(scancodeMakeP);
|
||||
injectKeyPress(scancodeMakeR);
|
||||
injectKeyPress(scancodeMakeI);
|
||||
injectKeyPress(scancodeMakeN);
|
||||
}
|
||||
|
||||
void kmain(uint32 magic, uint64 multibootInfo)
|
||||
|
||||
Reference in new issue
Block a user