From db4811a421901da33b6e301e4539d352d2f0798a Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Tue, 14 Apr 2026 18:13:35 +0800 Subject: [PATCH] Stage 29A --- clks/include/clks/exec.h | 1 + clks/kernel/exec.c | 419 +++++++++++++++++++++++++++------------ clks/kernel/kmain.c | 1 + 3 files changed, 297 insertions(+), 124 deletions(-) diff --git a/clks/include/clks/exec.h b/clks/include/clks/exec.h index 6fda6ae..b4704f9 100644 --- a/clks/include/clks/exec.h +++ b/clks/include/clks/exec.h @@ -11,6 +11,7 @@ clks_bool clks_exec_request_exit(u64 status); u64 clks_exec_current_pid(void); u64 clks_exec_sleep_ticks(u64 ticks); u64 clks_exec_yield(void); +void clks_exec_tick(u64 tick); u64 clks_exec_request_count(void); u64 clks_exec_success_count(void); clks_bool clks_exec_is_running(void); diff --git a/clks/kernel/exec.c b/clks/kernel/exec.c index 6de92cc..0bf8a0c 100644 --- a/clks/kernel/exec.c +++ b/clks/kernel/exec.c @@ -17,8 +17,9 @@ typedef u64 (*clks_exec_entry_fn)(void); enum clks_exec_proc_state { CLKS_EXEC_PROC_UNUSED = 0, - CLKS_EXEC_PROC_RUNNING = 1, - CLKS_EXEC_PROC_EXITED = 2, + CLKS_EXEC_PROC_PENDING = 1, + CLKS_EXEC_PROC_RUNNING = 2, + CLKS_EXEC_PROC_EXITED = 3, }; struct clks_exec_proc_record { @@ -39,6 +40,7 @@ extern u64 clks_exec_call_on_stack_x86_64(void *entry_ptr, void *stack_top); static u64 clks_exec_requests = 0ULL; static u64 clks_exec_success = 0ULL; static u32 clks_exec_running_depth = 0U; +static clks_bool clks_exec_pending_dispatch_active = CLKS_FALSE; static struct clks_exec_proc_record clks_exec_proc_table[CLKS_EXEC_MAX_PROCS]; static u64 clks_exec_next_pid = 1ULL; @@ -163,6 +165,51 @@ static i32 clks_exec_current_depth_index(void) { return (i32)(clks_exec_pid_stack_depth - 1U); } +static u64 clks_exec_alloc_pid(void) { + u64 pid = clks_exec_next_pid; + + clks_exec_next_pid++; + + if (clks_exec_next_pid == 0ULL) { + clks_exec_next_pid = 1ULL; + } + + if (pid == 0ULL) { + pid = clks_exec_next_pid; + clks_exec_next_pid++; + + if (clks_exec_next_pid == 0ULL) { + clks_exec_next_pid = 1ULL; + } + } + + return pid; +} + +static struct clks_exec_proc_record *clks_exec_prepare_proc_record(i32 slot, + u64 pid, + const char *path, + enum clks_exec_proc_state state) { + struct clks_exec_proc_record *proc; + + if (slot < 0 || path == CLKS_NULL) { + return CLKS_NULL; + } + + proc = &clks_exec_proc_table[(u32)slot]; + clks_memset(proc, 0, sizeof(*proc)); + + proc->used = CLKS_TRUE; + proc->state = state; + proc->pid = pid; + proc->ppid = clks_exec_current_pid(); + proc->started_tick = 0ULL; + proc->exited_tick = 0ULL; + proc->exit_status = (u64)-1; + clks_exec_copy_path(proc->path, sizeof(proc->path), path); + return proc; +} + static clks_bool clks_exec_invoke_entry(void *entry_ptr, u64 *out_ret) { if (entry_ptr == CLKS_NULL || out_ret == CLKS_NULL) { return CLKS_FALSE; @@ -189,22 +236,188 @@ static clks_bool clks_exec_invoke_entry(void *entry_ptr, u64 *out_ret) { #endif } -static clks_bool clks_exec_run_path_internal(const char *path, u64 *out_status, u64 *out_pid) { +static clks_bool clks_exec_run_proc_slot(i32 slot, u64 *out_status) { + struct clks_exec_proc_record *proc; const void *image; u64 image_size = 0ULL; struct clks_elf64_info info; struct clks_elf64_loaded_image loaded; clks_bool loaded_active = CLKS_FALSE; + clks_bool depth_pushed = CLKS_FALSE; + clks_bool depth_counted = CLKS_FALSE; void *entry_ptr; u64 run_ret = (u64)-1; - u64 pid = (u64)-1; - i32 slot; i32 depth_index; - struct clks_exec_proc_record *proc; clks_memset(&loaded, 0, sizeof(loaded)); - clks_exec_requests++; + if (out_status != CLKS_NULL) { + *out_status = (u64)-1; + } + + if (slot < 0 || (u32)slot >= CLKS_EXEC_MAX_PROCS) { + return CLKS_FALSE; + } + + proc = &clks_exec_proc_table[(u32)slot]; + + if (proc->used == CLKS_FALSE) { + return CLKS_FALSE; + } + + if (proc->path[0] != '/') { + proc->state = CLKS_EXEC_PROC_EXITED; + proc->exit_status = (u64)-1; + proc->exited_tick = clks_interrupts_timer_ticks(); + return CLKS_FALSE; + } + + if (clks_exec_pid_stack_depth >= CLKS_EXEC_MAX_DEPTH) { + clks_log(CLKS_LOG_WARN, "EXEC", "PROCESS STACK DEPTH EXCEEDED"); + proc->state = CLKS_EXEC_PROC_EXITED; + proc->exit_status = (u64)-1; + proc->exited_tick = clks_interrupts_timer_ticks(); + return CLKS_FALSE; + } + + proc->state = CLKS_EXEC_PROC_RUNNING; + proc->started_tick = clks_interrupts_timer_ticks(); + + depth_index = (i32)clks_exec_pid_stack_depth; + clks_exec_pid_stack[(u32)depth_index] = proc->pid; + clks_exec_exit_requested_stack[(u32)depth_index] = CLKS_FALSE; + clks_exec_exit_status_stack[(u32)depth_index] = 0ULL; + clks_exec_pid_stack_depth++; + depth_pushed = CLKS_TRUE; + + image = clks_fs_read_all(proc->path, &image_size); + + if (image == CLKS_NULL || image_size == 0ULL) { + clks_log(CLKS_LOG_WARN, "EXEC", "EXEC FILE MISSING"); + clks_log(CLKS_LOG_WARN, "EXEC", proc->path); + goto fail; + } + + if (clks_elf64_inspect(image, image_size, &info) == CLKS_FALSE) { + clks_log(CLKS_LOG_WARN, "EXEC", "EXEC ELF INVALID"); + clks_log(CLKS_LOG_WARN, "EXEC", proc->path); + goto fail; + } + + if (clks_elf64_load(image, image_size, &loaded) == CLKS_FALSE) { + clks_log(CLKS_LOG_WARN, "EXEC", "EXEC ELF LOAD FAILED"); + clks_log(CLKS_LOG_WARN, "EXEC", proc->path); + goto fail; + } + + loaded_active = CLKS_TRUE; + + entry_ptr = clks_elf64_entry_pointer(&loaded, info.entry); + if (entry_ptr == CLKS_NULL) { + clks_log(CLKS_LOG_WARN, "EXEC", "ENTRY POINTER RESOLVE FAILED"); + clks_log(CLKS_LOG_WARN, "EXEC", proc->path); + goto fail; + } + + clks_log(CLKS_LOG_INFO, "EXEC", "EXEC RUN START"); + clks_log(CLKS_LOG_INFO, "EXEC", proc->path); + clks_log_hex(CLKS_LOG_INFO, "EXEC", "ENTRY", info.entry); + clks_log_hex(CLKS_LOG_INFO, "EXEC", "PHNUM", (u64)info.phnum); + + clks_exec_running_depth++; + depth_counted = CLKS_TRUE; + + if (clks_exec_invoke_entry(entry_ptr, &run_ret) == CLKS_FALSE) { + clks_log(CLKS_LOG_WARN, "EXEC", "EXEC RUN INVOKE FAILED"); + clks_log(CLKS_LOG_WARN, "EXEC", proc->path); + goto fail; + } + + if (depth_counted == CLKS_TRUE && clks_exec_running_depth > 0U) { + clks_exec_running_depth--; + depth_counted = CLKS_FALSE; + } + + if (clks_exec_exit_requested_stack[(u32)depth_index] == CLKS_TRUE) { + run_ret = clks_exec_exit_status_stack[(u32)depth_index]; + } + + clks_log(CLKS_LOG_INFO, "EXEC", "RUN RETURNED"); + clks_log(CLKS_LOG_INFO, "EXEC", proc->path); + clks_log_hex(CLKS_LOG_INFO, "EXEC", "RET", run_ret); + + clks_exec_success++; + + proc->state = CLKS_EXEC_PROC_EXITED; + proc->exit_status = run_ret; + proc->exited_tick = clks_interrupts_timer_ticks(); + + if (depth_pushed == CLKS_TRUE && clks_exec_pid_stack_depth > 0U) { + clks_exec_pid_stack_depth--; + depth_pushed = CLKS_FALSE; + } + + if (loaded_active == CLKS_TRUE) { + clks_elf64_unload(&loaded); + } + + if (out_status != CLKS_NULL) { + *out_status = run_ret; + } + + return CLKS_TRUE; + +fail: + if (depth_counted == CLKS_TRUE && clks_exec_running_depth > 0U) { + clks_exec_running_depth--; + } + + proc->state = CLKS_EXEC_PROC_EXITED; + proc->exit_status = (u64)-1; + proc->exited_tick = clks_interrupts_timer_ticks(); + + if (depth_pushed == CLKS_TRUE && clks_exec_pid_stack_depth > 0U) { + clks_exec_pid_stack_depth--; + } + + if (loaded_active == CLKS_TRUE) { + clks_elf64_unload(&loaded); + } + + if (out_status != CLKS_NULL) { + *out_status = (u64)-1; + } + + return CLKS_FALSE; +} + +static clks_bool clks_exec_dispatch_pending_once(void) { + u32 i; + + if (clks_exec_pending_dispatch_active == CLKS_TRUE) { + return CLKS_FALSE; + } + + for (i = 0U; i < CLKS_EXEC_MAX_PROCS; i++) { + if (clks_exec_proc_table[i].used == CLKS_TRUE && + clks_exec_proc_table[i].state == CLKS_EXEC_PROC_PENDING) { + u64 ignored_status = (u64)-1; + + clks_exec_pending_dispatch_active = CLKS_TRUE; + (void)clks_exec_run_proc_slot((i32)i, &ignored_status); + clks_exec_pending_dispatch_active = CLKS_FALSE; + return CLKS_TRUE; + } + } + + return CLKS_FALSE; +} + +static clks_bool clks_exec_run_path_internal(const char *path, u64 *out_status, u64 *out_pid) { + i32 slot; + u64 pid; + struct clks_exec_proc_record *proc; + u64 status = (u64)-1; if (out_status != CLKS_NULL) { *out_status = (u64)-1; @@ -214,6 +427,8 @@ static clks_bool clks_exec_run_path_internal(const char *path, u64 *out_status, *out_pid = (u64)-1; } + clks_exec_requests++; + if (path == CLKS_NULL || path[0] != '/') { clks_log(CLKS_LOG_WARN, "EXEC", "INVALID EXEC PATH"); return CLKS_FALSE; @@ -226,136 +441,33 @@ static clks_bool clks_exec_run_path_internal(const char *path, u64 *out_status, return CLKS_FALSE; } - if (clks_exec_pid_stack_depth >= CLKS_EXEC_MAX_DEPTH) { - clks_log(CLKS_LOG_WARN, "EXEC", "PROCESS STACK DEPTH EXCEEDED"); + pid = clks_exec_alloc_pid(); + proc = clks_exec_prepare_proc_record(slot, pid, path, CLKS_EXEC_PROC_RUNNING); + + if (proc == CLKS_NULL) { return CLKS_FALSE; } - pid = clks_exec_next_pid; - clks_exec_next_pid++; - - if (clks_exec_next_pid == 0ULL) { - clks_exec_next_pid = 1ULL; - } - - proc = &clks_exec_proc_table[(u32)slot]; - clks_memset(proc, 0, sizeof(*proc)); - - proc->used = CLKS_TRUE; - proc->state = CLKS_EXEC_PROC_RUNNING; - proc->pid = pid; - proc->ppid = clks_exec_current_pid(); - proc->started_tick = clks_interrupts_timer_ticks(); - proc->exit_status = (u64)-1; - clks_exec_copy_path(proc->path, sizeof(proc->path), path); - - depth_index = (i32)clks_exec_pid_stack_depth; - clks_exec_pid_stack[(u32)depth_index] = pid; - clks_exec_exit_requested_stack[(u32)depth_index] = CLKS_FALSE; - clks_exec_exit_status_stack[(u32)depth_index] = 0ULL; - clks_exec_pid_stack_depth++; - - image = clks_fs_read_all(path, &image_size); - - if (image == CLKS_NULL || image_size == 0ULL) { - clks_log(CLKS_LOG_WARN, "EXEC", "EXEC FILE MISSING"); - clks_log(CLKS_LOG_WARN, "EXEC", path); - goto fail; - } - - if (clks_elf64_inspect(image, image_size, &info) == CLKS_FALSE) { - clks_log(CLKS_LOG_WARN, "EXEC", "EXEC ELF INVALID"); - clks_log(CLKS_LOG_WARN, "EXEC", path); - goto fail; - } - - if (clks_elf64_load(image, image_size, &loaded) == CLKS_FALSE) { - clks_log(CLKS_LOG_WARN, "EXEC", "EXEC ELF LOAD FAILED"); - clks_log(CLKS_LOG_WARN, "EXEC", path); - goto fail; - } - - loaded_active = CLKS_TRUE; - - entry_ptr = clks_elf64_entry_pointer(&loaded, info.entry); - if (entry_ptr == CLKS_NULL) { - clks_log(CLKS_LOG_WARN, "EXEC", "ENTRY POINTER RESOLVE FAILED"); - clks_log(CLKS_LOG_WARN, "EXEC", path); - goto fail; - } - - clks_log(CLKS_LOG_INFO, "EXEC", "EXEC RUN START"); - clks_log(CLKS_LOG_INFO, "EXEC", path); - clks_log_hex(CLKS_LOG_INFO, "EXEC", "ENTRY", info.entry); - clks_log_hex(CLKS_LOG_INFO, "EXEC", "PHNUM", (u64)info.phnum); - - clks_exec_running_depth++; - if (clks_exec_invoke_entry(entry_ptr, &run_ret) == CLKS_FALSE) { - if (clks_exec_running_depth > 0U) { - clks_exec_running_depth--; - } - - clks_log(CLKS_LOG_WARN, "EXEC", "EXEC RUN INVOKE FAILED"); - clks_log(CLKS_LOG_WARN, "EXEC", path); - goto fail; - } - - if (clks_exec_running_depth > 0U) { - clks_exec_running_depth--; - } - - if (clks_exec_exit_requested_stack[(u32)depth_index] == CLKS_TRUE) { - run_ret = clks_exec_exit_status_stack[(u32)depth_index]; - } - - clks_log(CLKS_LOG_INFO, "EXEC", "RUN RETURNED"); - clks_log(CLKS_LOG_INFO, "EXEC", path); - clks_log_hex(CLKS_LOG_INFO, "EXEC", "RET", run_ret); - - clks_exec_success++; - - proc->state = CLKS_EXEC_PROC_EXITED; - proc->exit_status = run_ret; - proc->exited_tick = clks_interrupts_timer_ticks(); - - clks_exec_pid_stack_depth--; - - if (loaded_active == CLKS_TRUE) { - clks_elf64_unload(&loaded); - } - - if (out_status != CLKS_NULL) { - *out_status = run_ret; - } - if (out_pid != CLKS_NULL) { *out_pid = pid; } - return CLKS_TRUE; - -fail: - proc->state = CLKS_EXEC_PROC_EXITED; - proc->exit_status = (u64)-1; - proc->exited_tick = clks_interrupts_timer_ticks(); - - clks_exec_pid_stack_depth--; - - if (loaded_active == CLKS_TRUE) { - clks_elf64_unload(&loaded); + if (clks_exec_run_proc_slot(slot, &status) == CLKS_FALSE) { + return CLKS_FALSE; } if (out_status != CLKS_NULL) { - *out_status = (u64)-1; + *out_status = status; } - return CLKS_FALSE; + return CLKS_TRUE; } void clks_exec_init(void) { clks_exec_requests = 0ULL; clks_exec_success = 0ULL; clks_exec_running_depth = 0U; + clks_exec_pending_dispatch_active = CLKS_FALSE; clks_exec_next_pid = 1ULL; clks_exec_pid_stack_depth = 0U; clks_memset(clks_exec_pid_stack, 0, sizeof(clks_exec_pid_stack)); @@ -370,13 +482,49 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) { } clks_bool clks_exec_spawn_path(const char *path, u64 *out_pid) { - u64 status = (u64)-1; - return clks_exec_run_path_internal(path, &status, out_pid); + i32 slot; + u64 pid; + struct clks_exec_proc_record *proc; + + if (out_pid != CLKS_NULL) { + *out_pid = (u64)-1; + } + + clks_exec_requests++; + + if (path == CLKS_NULL || path[0] != '/') { + clks_log(CLKS_LOG_WARN, "EXEC", "INVALID SPAWN PATH"); + return CLKS_FALSE; + } + + slot = clks_exec_proc_alloc_slot(); + + if (slot < 0) { + clks_log(CLKS_LOG_WARN, "EXEC", "PROCESS TABLE FULL"); + return CLKS_FALSE; + } + + pid = clks_exec_alloc_pid(); + proc = clks_exec_prepare_proc_record(slot, pid, path, CLKS_EXEC_PROC_PENDING); + + if (proc == CLKS_NULL) { + return CLKS_FALSE; + } + + if (out_pid != CLKS_NULL) { + *out_pid = pid; + } + + clks_log(CLKS_LOG_INFO, "EXEC", "SPAWN QUEUED"); + clks_log(CLKS_LOG_INFO, "EXEC", path); + clks_log_hex(CLKS_LOG_INFO, "EXEC", "PID", pid); + + return CLKS_TRUE; } u64 clks_exec_wait_pid(u64 pid, u64 *out_status) { i32 slot; - const struct clks_exec_proc_record *proc; + struct clks_exec_proc_record *proc; slot = clks_exec_proc_find_slot_by_pid(pid); @@ -386,10 +534,26 @@ u64 clks_exec_wait_pid(u64 pid, u64 *out_status) { proc = &clks_exec_proc_table[(u32)slot]; - if (proc->state == CLKS_EXEC_PROC_RUNNING) { + if (proc->used == CLKS_FALSE) { + return (u64)-1; + } + + if (proc->state == CLKS_EXEC_PROC_PENDING && clks_exec_pending_dispatch_active == CLKS_FALSE) { + u64 ignored_status = (u64)-1; + + clks_exec_pending_dispatch_active = CLKS_TRUE; + (void)clks_exec_run_proc_slot(slot, &ignored_status); + clks_exec_pending_dispatch_active = CLKS_FALSE; + } + + if (proc->state == CLKS_EXEC_PROC_PENDING || proc->state == CLKS_EXEC_PROC_RUNNING) { return 0ULL; } + if (proc->state != CLKS_EXEC_PROC_EXITED) { + return (u64)-1; + } + if (out_status != CLKS_NULL) { *out_status = proc->exit_status; } @@ -432,6 +596,7 @@ u64 clks_exec_sleep_ticks(u64 ticks) { #elif defined(CLKS_ARCH_AARCH64) clks_cpu_pause(); #endif + (void)clks_exec_dispatch_pending_once(); } return clks_interrupts_timer_ticks() - start; @@ -444,9 +609,15 @@ u64 clks_exec_yield(void) { clks_cpu_pause(); #endif + (void)clks_exec_dispatch_pending_once(); return clks_interrupts_timer_ticks(); } +void clks_exec_tick(u64 tick) { + (void)tick; + (void)clks_exec_dispatch_pending_once(); +} + u64 clks_exec_request_count(void) { return clks_exec_requests; } @@ -478,4 +649,4 @@ clks_bool clks_exec_current_path_is_user(void) { proc = &clks_exec_proc_table[(u32)slot]; return clks_exec_path_is_user_program(proc->path); -} +} \ No newline at end of file diff --git a/clks/kernel/kmain.c b/clks/kernel/kmain.c index 619567f..b5b3d52 100644 --- a/clks/kernel/kmain.c +++ b/clks/kernel/kmain.c @@ -66,6 +66,7 @@ static void clks_task_kelfd(u64 tick) { static void clks_task_usrd(u64 tick) { clks_service_heartbeat(CLKS_SERVICE_USER, tick); + clks_exec_tick(tick); clks_userland_tick(tick); clks_desktop_tick(tick); clks_tty_tick(tick);