Add command task execution and improve command documentation

Introduced a new CommandTaskContext structure to facilitate command execution in separate tasks. Updated the execute_command function to spawn tasks for commands, enhancing concurrency. Improved documentation for the 'memtest' and 'tasktest' commands in README.md to clarify their functionality and usage. Updated the interactive prompt reference to 'starling>'.
This commit is contained in:
2026-02-27 20:14:11 +00:00
parent d17daf7aac
commit 7ecf26cbd9
2 changed files with 107 additions and 13 deletions

View File

@@ -40,6 +40,32 @@ static void cmd_spawn(BootInfo *Boot, CHAR16 *Args);
static void cmd_memtest(BootInfo *Boot, CHAR16 *Args);
static void cmd_tasktest(BootInfo *Boot, CHAR16 *Args);
/* Small helper struct used to pass arguments into per-command tasks. */
typedef struct {
BootInfo *Boot;
CommandHandlerFn handler;
CHAR16 args[128];
} CommandTaskContext;
static void command_task_entry(void *arg);
/* Local string copy helper (wide-char, bounded). */
static void wstrcpy16_local(CHAR16 *dst, const CHAR16 *src, UINTN max)
{
UINTN i = 0;
if (dst == NULL || max == 0) {
return;
}
while (src != NULL && src[i] != L'\0' && i < (max - 1)) {
dst[i] = src[i];
i++;
}
dst[i] = L'\0';
}
/* ================================================================
* Command registry
* ================================================================ */
@@ -96,13 +122,22 @@ static Command commands[] = {
{
L"memtest",
L"Test memory allocation and deallocation",
L"Usage: memtest\n\r Allocates and frees heap and page memory to verify\n\r the memory manager is working correctly.",
L"Usage: memtest\n\r"
L" Run memory tests in four phases:\n\r"
L" 1) Heap allocation of 8 blocks (164096 bytes) via kmalloc()\n\r"
L" 2) Heap free and coalescing verification via kfree()\n\r"
L" 3) Single-page PMM allocate/free via pmm_alloc_page()/pmm_free_page()\n\r"
L" 4) Multi-page (4-page) PMM allocate/free via pmm_alloc_pages()/pmm_free_pages()\n\r",
cmd_memtest
},
{
L"tasktest",
L"Test task scheduler with multiple tasks",
L"Usage: tasktest\n\r Spawns several concurrent tasks that run cooperatively\n\r and report their progress, demonstrating context switching.",
L"Usage: tasktest\n\r"
L" Spawns three worker tasks (worker-A/B/C) that run cooperatively,\n\r"
L" each printing three progress steps and yielding between them.\n\r"
L" After the workers finish, prints the final task list to\n\r"
L" demonstrate the cooperative round-robin scheduler.",
cmd_tasktest
},
{NULL, NULL, NULL, NULL} /* sentinel */
@@ -448,22 +483,29 @@ void show_help(BootInfo *Boot)
/*
* Parse a line of user input into command + arguments and dispatch
* to the matching handler. Unknown commands print an error.
* by spawning a dedicated task for the matching handler. Unknown
* commands print an error.
*
* Returns:
* - Pointer to the spawned Task for the command, or NULL if the
* command was not found or had to run synchronously.
*/
void execute_command(BootInfo *Boot, CHAR16 *Input)
Task *execute_command(BootInfo *Boot, CHAR16 *Input)
{
CHAR16 *cmd_start = NULL;
CHAR16 *args_start = NULL;
UINTN i = 0;
CommandTaskContext *ctx;
Task *t;
if (Boot == NULL || Input == NULL) {
return;
return NULL;
}
trim_spaces_inplace(Input);
if (Input[0] == L'\0') {
return;
return NULL;
}
/* Split input into command and argument strings */
@@ -489,12 +531,57 @@ void execute_command(BootInfo *Boot, CHAR16 *Input)
/* Look up and dispatch the command */
for (i = 0; commands[i].name != NULL; i++) {
if (ascii_streq_ci(cmd_start, commands[i].name)) {
commands[i].handler(Boot, args_start);
return;
/* Allocate a context block for the command task. */
ctx = (CommandTaskContext *)kmalloc(sizeof(CommandTaskContext));
if (ctx == NULL) {
SAFE_PRINT(Boot, L"Failed to allocate command context; running in core thread.\n\r");
commands[i].handler(Boot, args_start);
return NULL;
}
ctx->Boot = Boot;
ctx->handler = commands[i].handler;
wstrcpy16_local(ctx->args, args_start, sizeof(ctx->args) / sizeof(ctx->args[0]));
t = task_create(commands[i].name, command_task_entry, ctx);
if (t == NULL) {
SAFE_PRINT(Boot, L"Failed to create task for command '%s'; running in core thread.\n\r",
commands[i].name);
kfree(ctx);
commands[i].handler(Boot, args_start);
return NULL;
}
SAFE_PRINT(Boot, L"[starling] spawned '%s' as PID %d\n\r", t->name, t->pid);
return t;
}
}
/* Command not found */
SAFE_PRINT(Boot, L"Unknown command: %s\n\r", cmd_start);
SAFE_PRINT(Boot, L"Type 'help' for a list of available commands.\n\r");
return NULL;
}
/* ----------------------------------------------------------------
* Command task entry executes one command in its own task context
* ---------------------------------------------------------------- */
static void command_task_entry(void *arg)
{
CommandTaskContext *ctx = (CommandTaskContext *)arg;
BootInfo *Boot = NULL;
if (ctx == NULL) {
return;
}
Boot = ctx->Boot;
if (ctx->handler != NULL) {
ctx->handler(Boot, ctx->args);
}
/* Context was heap-allocated in execute_command. */
kfree(ctx);
}