diff --git a/src/kmain.c b/src/kmain.c index 40f8563..be96dc4 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -1960,8 +1960,113 @@ void kmain(uint32 magic, uint64 multibootInfo) spawnUser("/bin/counter", "counter", 0x58000000, 0); spawnUser("/bin/sbrktest", "sbrktest", 0x68000000, 0x64000000); spawnUser("/bin/fileread", "fileread", 0x78000000, 0); + spawnUser("/bin/pipetest", "pipetest", 0x88000000, 0); + spawnUser("/bin/disktest", "disktest", 0x98000000, 0); + spawnUser("/bin/fstest", "fstest", 0xA8000000, 0); + spawnUser("/bin/linktest", "linktest", 0xB8000000, 0); + spawnUser("/bin/fifomaster", "fifomaster", 0x118000000, 0); + spawnUser("/bin/killtest", "killtest", 0x148000000, 0); + spawnUser("/bin/namedreader", "namedreader", 0x168000000, 0); + spawnUser("/bin/namedwriter", "namedwriter", 0x178000000, 0); + spawnUser("/bin/consolereader1", "consolereader1", 0x188000000, 0); + spawnUser("/bin/consolereader2", "consolereader2", 0x198000000, 0); + threadCreate("consoleInjector", consoleInjectorThread); + spawnUser("/bin/sigtest", "sigtest", 0x1A8000000, 0); + spawnUser("/bin/jobtest", "jobtest", 0x1D8000000, 0); + spawnUser("/bin/nesttest", "nesttest", 0x1F8000000, 0); + spawnUser("/bin/eintrtest", "eintrtest", 0x218000000, 0); + spawnUser("/bin/restarttest", "restarttest", 0x238000000, 0); + spawnUser("/bin/masktest", "masktest", 0x258000000, 0); + spawnUser("/bin/sigchldtest", "sigchldtest", 0x278000000, 0); + spawnUser("/bin/waitanytest", "waitanytest", 0x298000000, 0); + spawnUser("/bin/stopchldtest", "stopchldtest", 0x2C8000000, 0); + spawnUser("/bin/nodefertest", "nodefertest", 0x2E8000000, 0); + spawnUser("/bin/alarmtest", "alarmtest", 0x2F8000000, 0); + spawnUser("/bin/siginfotest", "siginfotest", 0x318000000, 0); + spawnUser("/bin/selfstoptest", "selfstoptest", 0x3F8000000, 0); + spawnUser("/bin/cwdtest", "cwdtest", 0x458000000, 0); + spawnUser("/bin/nicetest", "nicetest", 0x4A8000000, 0); + spawnUser("/bin/date", "date", 0x4B8000000, 0); + spawnUser("/bin/timetest", "timetest", 0x4D8000000, 0); + spawnUser("/bin/rmtest", "rmtest", 0x508000000, 0); + spawnUser("/bin/permtest", "permtest", 0x518000000, 0); + spawnUser("/bin/identtest", "identtest", 0x528000000, 0); + spawnUser("/bin/dirpermtest", "dirpermtest", 0x538000000, 0); + spawnUser("/bin/grouptest", "grouptest", 0x548000000, 0); + spawnUser("/bin/pidfdtest", "pidfdtest", 0x558000000, 0); + /* mmapprotvictim and mmapexecvictim are deliberately NOT spawned here + -- like killvictim (killtest's own runtime-spawned target, elsewhere + in this function), both are only ever loaded at runtime, by + mmaptest itself (userSpawn), never directly by kmain.c. */ + spawnUser("/bin/mmaptest", "mmaptest", 0x568000000, 0); + spawnUser("/bin/polltest", "polltest", 0x378000000, 0); + pgroupfgPid = spawnUser("/bin/pgroupfg", "pgroupfg", 0x338000000, 0); + pgroupbgPid = spawnUser("/bin/pgroupbg", "pgroupbg", 0x348000000, 0); + if (pgroupfgPid != threadInvalidId) { + /* Real shell/tcsetpgrp behavior: whichever job was just launched in + the foreground claims the terminal explicitly -- pgroupbg is + deliberately left alone (its own default group, never named + here), the same way a background job never touches the + controlling terminal at all. */ + keyboardSetForegroundPgid(pgroupfgPid); + } + if (pgroupfgPid != threadInvalidId && pgroupbgPid != threadInvalidId) + threadCreate("pgroupInjector", pgroupInjectorThread); + /* jobctlfg/jobctlbg are deliberately NOT spawned here -- unlike every + program above, they are only ever loaded on demand, at runtime, by + the real interactive shell (shellRun, threadCreate'd near the top of + this function) once jobctlDriverThread types their names at it. */ + threadCreate("jobctlDriver", jobctlDriverThread); + /* pipesrc/pipesink are, like jobctlfg/jobctlbg just above, deliberately + NOT spawned here -- loaded on demand by the real shell once + pipelineDriverThread types "pipesrc | pipesink" at it. */ + threadCreate("pipelineDriver", pipelineDriverThread); + /* redirwriter/redirreader are, like pipesrc/pipesink just above, + deliberately NOT spawned here -- loaded on demand by the real shell + once redirDriverThread types the redirected commands at it. */ + threadCreate("redirDriver", redirDriverThread); + /* stderrwriter/stderrreader are, like redirwriter/redirreader just + above, deliberately NOT spawned here -- loaded on demand by the real + shell once stderrDriverThread types the stderr-redirected commands + at it. */ + threadCreate("stderrDriver", stderrDriverThread); + /* herestest is, like stderrwriter/stderrreader just above, deliberately + NOT spawned here -- loaded on demand by the real shell once + hereDriverThread types the here-string command at it. */ + threadCreate("hereDriver", hereDriverThread); + /* hcat/hsink are, like herestest just above, deliberately NOT spawned + here -- loaded on demand by the real shell once + hereStringPipelineDriverThread types the here-string-into-pipeline + command at it. */ + threadCreate("hereStringPipelineDriver", hereStringPipelineDriverThread); + /* pipecat is, like hcat/hsink just above, deliberately NOT spawned here + -- loaded on demand by the real shell once + threeStagePipelineDriverThread types the three-stage pipeline + command at it (pipesrc/pipesink themselves are also on-demand-only, + unchanged since FALA 29). */ + threadCreate("threeStagePipelineDriver", threeStagePipelineDriverThread); + /* envprint is, like pipecat just above, deliberately NOT spawned here + -- loaded on demand by the real shell once envDriverThread types + "export GREETING=frostbyte" then "envprint" at it. */ + threadCreate("envDriver", envDriverThread); + /* globcat is, like envprint just above, deliberately NOT spawned here + -- loaded on demand by the real shell once globDriverThread types + "globcat /tmp/gd/ *.txt" at it (shell.c's new wildcard glob + expansion). */ + threadCreate("globDriver", globDriverThread); + /* No new /bin binary here -- lsDriverThread only exercises shell.c's + existing mkdir/echo/ls builtins, never spawns anything. */ + threadCreate("lsDriver", lsDriverThread); + /* false is, like globcat above, deliberately NOT spawned here -- + loaded on demand by the real shell once andOrDriverThread types the + `&&`/`||`-chained command at it (shell.c's new conditional + chaining). */ + threadCreate("andOrDriver", andOrDriverThread); + execDemoPid = spawnUser("/bin/proctest", "proctest", 0xF8000000, 0); + if (execDemoPid != threadInvalidId) + threadCreate("execReaper", execReaperThread); - kprintf("[sched] %u threads total (idle, shell, 2 workers, user programs)\n", + kprintf("[sched] %u threads total (idle, shell, 2 workers, priority verifier, user programs)\n", threadCount()); kprintf("\n[boot] enabling interrupts, starting preemptive scheduler\n\n"); diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..209357e --- /dev/null +++ b/src/list.c @@ -0,0 +1,61 @@ +#include "list.h" + +void listInit(ListNode* head) +{ + head->next = head; + head->prev = head; +} + +bool listEmpty(const ListNode* head) +{ + return head->next == head; +} + +void listInsertAfter(ListNode* pos, ListNode* newNode) +{ + newNode->prev = pos; + newNode->next = pos->next; + pos->next->prev = newNode; + pos->next = newNode; +} + +void listInsertBefore(ListNode* pos, ListNode* newNode) +{ + listInsertAfter(pos->prev, newNode); +} + +void listPushBack(ListNode* head, ListNode* newNode) +{ + listInsertBefore(head, newNode); +} + +void listPushFront(ListNode* head, ListNode* newNode) +{ + listInsertAfter(head, newNode); +} + +void listRemove(ListNode* node) +{ + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = node; + node->prev = node; +} + +usize listLen(const ListNode* head) +{ + usize count = 0; + for (const ListNode* cursor = head->next; cursor != head; cursor = cursor->next) + count++; + return count; +} + +ListNode* listFront(const ListNode* head) +{ + return listEmpty(head) ? nullptr : head->next; +} + +ListNode* listBack(const ListNode* head) +{ + return listEmpty(head) ? nullptr : head->prev; +}