This commit is contained in:
2026-04-13 19:08:35 +08:00
parent 775a2f435d
commit 4beaed4ba3
15 changed files with 718 additions and 35 deletions

View File

@@ -127,6 +127,12 @@ static int ush_cmd_help(void) {
ush_writeln(" cp <src> <dst> (dst /temp only)"); ush_writeln(" cp <src> <dst> (dst /temp only)");
ush_writeln(" mv <src> <dst> (/temp only)"); ush_writeln(" mv <src> <dst> (/temp only)");
ush_writeln(" rm <path> (/temp only)"); ush_writeln(" rm <path> (/temp only)");
ush_writeln(" pid");
ush_writeln(" spawn <path|name>");
ush_writeln(" wait <pid>");
ush_writeln(" sleep <ticks>");
ush_writeln(" yield");
ush_writeln(" exit [code]");
ush_writeln(" rusttest / panic / elfloader (kernel shell only)"); ush_writeln(" rusttest / panic / elfloader (kernel shell only)");
ush_writeln("edit keys: Left/Right, Home/End, Up/Down history"); ush_writeln("edit keys: Left/Right, Home/End, Up/Down history");
return 1; return 1;
@@ -283,6 +289,114 @@ static int ush_cmd_exec(const ush_state *sh, const char *arg) {
return 0; return 0;
} }
static int ush_cmd_pid(void) {
ush_print_kv_hex("PID", cleonos_sys_getpid());
return 1;
}
static int ush_cmd_spawn(const ush_state *sh, const char *arg) {
char path[USH_PATH_MAX];
u64 pid;
if (ush_resolve_exec_path(sh, arg, path, (u64)sizeof(path)) == 0) {
ush_writeln("spawn: invalid target");
return 0;
}
if (ush_path_is_under_system(path) != 0) {
ush_writeln("spawn: /system/*.elf is kernel-mode (KELF), not user-exec");
return 0;
}
pid = cleonos_sys_spawn_path(path);
if (pid == (u64)-1) {
ush_writeln("spawn: request failed");
return 0;
}
ush_writeln("spawn: completed");
ush_print_kv_hex(" PID", pid);
return 1;
}
static int ush_cmd_wait(const char *arg) {
u64 pid;
u64 status = (u64)-1;
u64 wait_ret;
if (arg == (const char *)0 || arg[0] == '\0') {
ush_writeln("wait: usage wait <pid>");
return 0;
}
if (ush_parse_u64_dec(arg, &pid) == 0) {
ush_writeln("wait: invalid pid");
return 0;
}
wait_ret = cleonos_sys_wait_pid(pid, &status);
if (wait_ret == (u64)-1) {
ush_writeln("wait: pid not found");
return 0;
}
if (wait_ret == 0ULL) {
ush_writeln("wait: still running");
return 1;
}
ush_writeln("wait: exited");
ush_print_kv_hex(" STATUS", status);
return 1;
}
static int ush_cmd_sleep(const char *arg) {
u64 ticks;
u64 elapsed;
if (arg == (const char *)0 || arg[0] == '\0') {
ush_writeln("sleep: usage sleep <ticks>");
return 0;
}
if (ush_parse_u64_dec(arg, &ticks) == 0) {
ush_writeln("sleep: invalid ticks");
return 0;
}
elapsed = cleonos_sys_sleep_ticks(ticks);
ush_print_kv_hex("SLEPT_TICKS", elapsed);
return 1;
}
static int ush_cmd_yield(void) {
ush_print_kv_hex("YIELD_TICK", cleonos_sys_yield());
return 1;
}
static int ush_cmd_exit(ush_state *sh, const char *arg) {
u64 code = 0ULL;
if (sh == (ush_state *)0) {
return 0;
}
if (arg != (const char *)0 && arg[0] != '\0') {
if (ush_parse_u64_dec(arg, &code) == 0) {
ush_writeln("exit: usage exit [code]");
return 0;
}
}
sh->exit_requested = 1;
sh->exit_code = code;
(void)cleonos_sys_exit(code);
ush_writeln("exit: shell stopping");
return 1;
}
static int ush_cmd_clear(void) { static int ush_cmd_clear(void) {
u64 i; u64 i;
@@ -352,6 +466,8 @@ static int ush_cmd_shstat(const ush_state *sh) {
ush_print_kv_hex(" CMD_OK", sh->cmd_ok); ush_print_kv_hex(" CMD_OK", sh->cmd_ok);
ush_print_kv_hex(" CMD_FAIL", sh->cmd_fail); ush_print_kv_hex(" CMD_FAIL", sh->cmd_fail);
ush_print_kv_hex(" CMD_UNKNOWN", sh->cmd_unknown); ush_print_kv_hex(" CMD_UNKNOWN", sh->cmd_unknown);
ush_print_kv_hex(" EXIT_REQUESTED", (sh->exit_requested != 0) ? 1ULL : 0ULL);
ush_print_kv_hex(" EXIT_CODE", sh->exit_code);
return 1; return 1;
} }
@@ -744,6 +860,18 @@ void ush_execute_line(ush_state *sh, const char *line) {
success = ush_cmd_cd(sh, arg); success = ush_cmd_cd(sh, arg);
} else if (ush_streq(cmd, "exec") != 0 || ush_streq(cmd, "run") != 0) { } else if (ush_streq(cmd, "exec") != 0 || ush_streq(cmd, "run") != 0) {
success = ush_cmd_exec(sh, arg); success = ush_cmd_exec(sh, arg);
} else if (ush_streq(cmd, "pid") != 0) {
success = ush_cmd_pid();
} else if (ush_streq(cmd, "spawn") != 0) {
success = ush_cmd_spawn(sh, arg);
} else if (ush_streq(cmd, "wait") != 0) {
success = ush_cmd_wait(arg);
} else if (ush_streq(cmd, "sleep") != 0) {
success = ush_cmd_sleep(arg);
} else if (ush_streq(cmd, "yield") != 0) {
success = ush_cmd_yield();
} else if (ush_streq(cmd, "exit") != 0) {
success = ush_cmd_exit(sh, arg);
} else if (ush_streq(cmd, "clear") != 0 || ush_streq(cmd, "cls") != 0) { } else if (ush_streq(cmd, "clear") != 0 || ush_streq(cmd, "cls") != 0) {
success = ush_cmd_clear(); success = ush_cmd_clear();
} else if (ush_streq(cmd, "memstat") != 0) { } else if (ush_streq(cmd, "memstat") != 0) {

View File

@@ -41,6 +41,8 @@ typedef struct ush_state {
u64 cmd_ok; u64 cmd_ok;
u64 cmd_fail; u64 cmd_fail;
u64 cmd_unknown; u64 cmd_unknown;
int exit_requested;
u64 exit_code;
} ush_state; } ush_state;
void ush_init_state(ush_state *sh); void ush_init_state(ush_state *sh);

View File

@@ -22,6 +22,8 @@ void ush_init_state(ush_state *sh) {
sh->cmd_ok = 0ULL; sh->cmd_ok = 0ULL;
sh->cmd_fail = 0ULL; sh->cmd_fail = 0ULL;
sh->cmd_unknown = 0ULL; sh->cmd_unknown = 0ULL;
sh->exit_requested = 0;
sh->exit_code = 0ULL;
} }
u64 ush_strlen(const char *str) { u64 ush_strlen(const char *str) {

View File

@@ -14,5 +14,9 @@ int cleonos_app_main(void) {
for (;;) { for (;;) {
ush_read_line(&sh, line, (u64)sizeof(line)); ush_read_line(&sh, line, (u64)sizeof(line));
ush_execute_line(&sh, line); ush_execute_line(&sh, line);
if (sh.exit_requested != 0) {
return (int)(sh.exit_code & 0x7FFFFFFFULL);
}
} }
} }

View File

@@ -46,6 +46,12 @@ typedef unsigned long long usize;
#define CLEONOS_SYSCALL_KBD_POPPED 37ULL #define CLEONOS_SYSCALL_KBD_POPPED 37ULL
#define CLEONOS_SYSCALL_KBD_DROPPED 38ULL #define CLEONOS_SYSCALL_KBD_DROPPED 38ULL
#define CLEONOS_SYSCALL_KBD_HOTKEY_SWITCHES 39ULL #define CLEONOS_SYSCALL_KBD_HOTKEY_SWITCHES 39ULL
#define CLEONOS_SYSCALL_GETPID 40ULL
#define CLEONOS_SYSCALL_SPAWN_PATH 41ULL
#define CLEONOS_SYSCALL_WAITPID 42ULL
#define CLEONOS_SYSCALL_EXIT 43ULL
#define CLEONOS_SYSCALL_SLEEP_TICKS 44ULL
#define CLEONOS_SYSCALL_YIELD 45ULL
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
u64 cleonos_sys_log_write(const char *message, u64 length); u64 cleonos_sys_log_write(const char *message, u64 length);
@@ -87,5 +93,11 @@ u64 cleonos_sys_kbd_pushed(void);
u64 cleonos_sys_kbd_popped(void); u64 cleonos_sys_kbd_popped(void);
u64 cleonos_sys_kbd_dropped(void); u64 cleonos_sys_kbd_dropped(void);
u64 cleonos_sys_kbd_hotkey_switches(void); u64 cleonos_sys_kbd_hotkey_switches(void);
u64 cleonos_sys_getpid(void);
u64 cleonos_sys_spawn_path(const char *path);
u64 cleonos_sys_wait_pid(u64 pid, u64 *out_status);
u64 cleonos_sys_exit(u64 status);
u64 cleonos_sys_sleep_ticks(u64 ticks);
u64 cleonos_sys_yield(void);
#endif #endif

View File

@@ -168,3 +168,27 @@ u64 cleonos_sys_kbd_dropped(void) {
u64 cleonos_sys_kbd_hotkey_switches(void) { u64 cleonos_sys_kbd_hotkey_switches(void) {
return cleonos_syscall(CLEONOS_SYSCALL_KBD_HOTKEY_SWITCHES, 0ULL, 0ULL, 0ULL); return cleonos_syscall(CLEONOS_SYSCALL_KBD_HOTKEY_SWITCHES, 0ULL, 0ULL, 0ULL);
} }
u64 cleonos_sys_getpid(void) {
return cleonos_syscall(CLEONOS_SYSCALL_GETPID, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_spawn_path(const char *path) {
return cleonos_syscall(CLEONOS_SYSCALL_SPAWN_PATH, (u64)path, 0ULL, 0ULL);
}
u64 cleonos_sys_wait_pid(u64 pid, u64 *out_status) {
return cleonos_syscall(CLEONOS_SYSCALL_WAITPID, pid, (u64)out_status, 0ULL);
}
u64 cleonos_sys_exit(u64 status) {
return cleonos_syscall(CLEONOS_SYSCALL_EXIT, status, 0ULL, 0ULL);
}
u64 cleonos_sys_sleep_ticks(u64 ticks) {
return cleonos_syscall(CLEONOS_SYSCALL_SLEEP_TICKS, ticks, 0ULL, 0ULL);
}
u64 cleonos_sys_yield(void) {
return cleonos_syscall(CLEONOS_SYSCALL_YIELD, 0ULL, 0ULL, 0ULL);
}

View File

@@ -5,9 +5,14 @@
void clks_exec_init(void); void clks_exec_init(void);
clks_bool clks_exec_run_path(const char *path, u64 *out_status); 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 clks_exec_wait_pid(u64 pid, u64 *out_status);
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);
u64 clks_exec_request_count(void); u64 clks_exec_request_count(void);
u64 clks_exec_success_count(void); u64 clks_exec_success_count(void);
clks_bool clks_exec_is_running(void); clks_bool clks_exec_is_running(void);
#endif #endif

View File

@@ -43,6 +43,12 @@
#define CLKS_SYSCALL_KBD_POPPED 37ULL #define CLKS_SYSCALL_KBD_POPPED 37ULL
#define CLKS_SYSCALL_KBD_DROPPED 38ULL #define CLKS_SYSCALL_KBD_DROPPED 38ULL
#define CLKS_SYSCALL_KBD_HOTKEY_SWITCHES 39ULL #define CLKS_SYSCALL_KBD_HOTKEY_SWITCHES 39ULL
#define CLKS_SYSCALL_GETPID 40ULL
#define CLKS_SYSCALL_SPAWN_PATH 41ULL
#define CLKS_SYSCALL_WAITPID 42ULL
#define CLKS_SYSCALL_EXIT 43ULL
#define CLKS_SYSCALL_SLEEP_TICKS 44ULL
#define CLKS_SYSCALL_YIELD 45ULL
void clks_syscall_init(void); void clks_syscall_init(void);
u64 clks_syscall_dispatch(void *frame_ptr); u64 clks_syscall_dispatch(void *frame_ptr);

View File

@@ -1,13 +1,36 @@
#include <clks/cpu.h>
#include <clks/elf64.h> #include <clks/elf64.h>
#include <clks/exec.h> #include <clks/exec.h>
#include <clks/fs.h> #include <clks/fs.h>
#include <clks/heap.h> #include <clks/heap.h>
#include <clks/interrupts.h>
#include <clks/log.h> #include <clks/log.h>
#include <clks/string.h>
#include <clks/types.h> #include <clks/types.h>
typedef u64 (*clks_exec_entry_fn)(void); typedef u64 (*clks_exec_entry_fn)(void);
#define CLKS_EXEC_RUN_STACK_BYTES (64ULL * 1024ULL) #define CLKS_EXEC_RUN_STACK_BYTES (64ULL * 1024ULL)
#define CLKS_EXEC_MAX_PROCS 64U
#define CLKS_EXEC_MAX_DEPTH 16U
#define CLKS_EXEC_PATH_MAX 192U
enum clks_exec_proc_state {
CLKS_EXEC_PROC_UNUSED = 0,
CLKS_EXEC_PROC_RUNNING = 1,
CLKS_EXEC_PROC_EXITED = 2,
};
struct clks_exec_proc_record {
clks_bool used;
enum clks_exec_proc_state state;
u64 pid;
u64 ppid;
u64 started_tick;
u64 exited_tick;
u64 exit_status;
char path[CLKS_EXEC_PATH_MAX];
};
#if defined(CLKS_ARCH_X86_64) #if defined(CLKS_ARCH_X86_64)
extern u64 clks_exec_call_on_stack_x86_64(void *entry_ptr, void *stack_top); extern u64 clks_exec_call_on_stack_x86_64(void *entry_ptr, void *stack_top);
@@ -17,6 +40,66 @@ static u64 clks_exec_requests = 0ULL;
static u64 clks_exec_success = 0ULL; static u64 clks_exec_success = 0ULL;
static u32 clks_exec_running_depth = 0U; static u32 clks_exec_running_depth = 0U;
static struct clks_exec_proc_record clks_exec_proc_table[CLKS_EXEC_MAX_PROCS];
static u64 clks_exec_next_pid = 1ULL;
static u64 clks_exec_pid_stack[CLKS_EXEC_MAX_DEPTH];
static clks_bool clks_exec_exit_requested_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_exit_status_stack[CLKS_EXEC_MAX_DEPTH];
static u32 clks_exec_pid_stack_depth = 0U;
static void clks_exec_copy_path(char *dst, usize dst_size, const char *src) {
usize i = 0U;
if (dst == CLKS_NULL || src == CLKS_NULL || dst_size == 0U) {
return;
}
while (src[i] != '\0' && i + 1U < dst_size) {
dst[i] = src[i];
i++;
}
dst[i] = '\0';
}
static i32 clks_exec_proc_find_slot_by_pid(u64 pid) {
u32 i;
for (i = 0U; i < CLKS_EXEC_MAX_PROCS; i++) {
if (clks_exec_proc_table[i].used == CLKS_TRUE && clks_exec_proc_table[i].pid == pid) {
return (i32)i;
}
}
return -1;
}
static i32 clks_exec_proc_alloc_slot(void) {
u32 i;
for (i = 0U; i < CLKS_EXEC_MAX_PROCS; i++) {
if (clks_exec_proc_table[i].used == CLKS_FALSE) {
return (i32)i;
}
}
for (i = 0U; i < CLKS_EXEC_MAX_PROCS; i++) {
if (clks_exec_proc_table[i].state == CLKS_EXEC_PROC_EXITED) {
return (i32)i;
}
}
return -1;
}
static i32 clks_exec_current_depth_index(void) {
if (clks_exec_pid_stack_depth == 0U) {
return -1;
}
return (i32)(clks_exec_pid_stack_depth - 1U);
}
static clks_bool clks_exec_invoke_entry(void *entry_ptr, u64 *out_ret) { static clks_bool clks_exec_invoke_entry(void *entry_ptr, u64 *out_ret) {
if (entry_ptr == CLKS_NULL || out_ret == CLKS_NULL) { if (entry_ptr == CLKS_NULL || out_ret == CLKS_NULL) {
return CLKS_FALSE; return CLKS_FALSE;
@@ -43,20 +126,20 @@ static clks_bool clks_exec_invoke_entry(void *entry_ptr, u64 *out_ret) {
#endif #endif
} }
void clks_exec_init(void) { static clks_bool clks_exec_run_path_internal(const char *path, u64 *out_status, u64 *out_pid) {
clks_exec_requests = 0ULL;
clks_exec_success = 0ULL;
clks_exec_running_depth = 0U;
clks_log(CLKS_LOG_INFO, "EXEC", "PATH EXEC FRAMEWORK ONLINE");
}
clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
const void *image; const void *image;
u64 image_size = 0ULL; u64 image_size = 0ULL;
struct clks_elf64_info info; struct clks_elf64_info info;
struct clks_elf64_loaded_image loaded; struct clks_elf64_loaded_image loaded;
clks_bool loaded_active = CLKS_FALSE;
void *entry_ptr; void *entry_ptr;
u64 run_ret; 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++; clks_exec_requests++;
@@ -64,37 +147,78 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
*out_status = (u64)-1; *out_status = (u64)-1;
} }
if (out_pid != CLKS_NULL) {
*out_pid = (u64)-1;
}
if (path == CLKS_NULL || path[0] != '/') { if (path == CLKS_NULL || path[0] != '/') {
clks_log(CLKS_LOG_WARN, "EXEC", "INVALID EXEC PATH"); clks_log(CLKS_LOG_WARN, "EXEC", "INVALID EXEC PATH");
return CLKS_FALSE; return CLKS_FALSE;
} }
slot = clks_exec_proc_alloc_slot();
if (slot < 0) {
clks_log(CLKS_LOG_WARN, "EXEC", "PROCESS TABLE FULL");
return CLKS_FALSE;
}
if (clks_exec_pid_stack_depth >= CLKS_EXEC_MAX_DEPTH) {
clks_log(CLKS_LOG_WARN, "EXEC", "PROCESS STACK DEPTH EXCEEDED");
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); image = clks_fs_read_all(path, &image_size);
if (image == CLKS_NULL || image_size == 0ULL) { if (image == CLKS_NULL || image_size == 0ULL) {
clks_log(CLKS_LOG_WARN, "EXEC", "EXEC FILE MISSING"); clks_log(CLKS_LOG_WARN, "EXEC", "EXEC FILE MISSING");
clks_log(CLKS_LOG_WARN, "EXEC", path); clks_log(CLKS_LOG_WARN, "EXEC", path);
return CLKS_FALSE; goto fail;
} }
if (clks_elf64_inspect(image, image_size, &info) == CLKS_FALSE) { 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", "EXEC ELF INVALID");
clks_log(CLKS_LOG_WARN, "EXEC", path); clks_log(CLKS_LOG_WARN, "EXEC", path);
return CLKS_FALSE; goto fail;
} }
if (clks_elf64_load(image, image_size, &loaded) == CLKS_FALSE) { 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", "EXEC ELF LOAD FAILED");
clks_log(CLKS_LOG_WARN, "EXEC", path); clks_log(CLKS_LOG_WARN, "EXEC", path);
return CLKS_FALSE; goto fail;
} }
loaded_active = CLKS_TRUE;
entry_ptr = clks_elf64_entry_pointer(&loaded, info.entry); entry_ptr = clks_elf64_entry_pointer(&loaded, info.entry);
if (entry_ptr == CLKS_NULL) { if (entry_ptr == CLKS_NULL) {
clks_log(CLKS_LOG_WARN, "EXEC", "ENTRY POINTER RESOLVE FAILED"); clks_log(CLKS_LOG_WARN, "EXEC", "ENTRY POINTER RESOLVE FAILED");
clks_log(CLKS_LOG_WARN, "EXEC", path); clks_log(CLKS_LOG_WARN, "EXEC", path);
clks_elf64_unload(&loaded); goto fail;
return CLKS_FALSE;
} }
clks_log(CLKS_LOG_INFO, "EXEC", "EXEC RUN START"); clks_log(CLKS_LOG_INFO, "EXEC", "EXEC RUN START");
@@ -110,25 +234,154 @@ clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
clks_log(CLKS_LOG_WARN, "EXEC", "EXEC RUN INVOKE FAILED"); clks_log(CLKS_LOG_WARN, "EXEC", "EXEC RUN INVOKE FAILED");
clks_log(CLKS_LOG_WARN, "EXEC", path); clks_log(CLKS_LOG_WARN, "EXEC", path);
clks_elf64_unload(&loaded); goto fail;
return CLKS_FALSE;
} }
if (clks_exec_running_depth > 0U) { if (clks_exec_running_depth > 0U) {
clks_exec_running_depth--; 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", "RUN RETURNED");
clks_log(CLKS_LOG_INFO, "EXEC", path); clks_log(CLKS_LOG_INFO, "EXEC", path);
clks_log_hex(CLKS_LOG_INFO, "EXEC", "RET", run_ret); clks_log_hex(CLKS_LOG_INFO, "EXEC", "RET", run_ret);
clks_exec_success++; 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) { if (out_status != CLKS_NULL) {
*out_status = run_ret; *out_status = run_ret;
} }
clks_elf64_unload(&loaded); if (out_pid != CLKS_NULL) {
*out_pid = pid;
}
return CLKS_TRUE; 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 (out_status != CLKS_NULL) {
*out_status = (u64)-1;
}
return CLKS_FALSE;
}
void clks_exec_init(void) {
clks_exec_requests = 0ULL;
clks_exec_success = 0ULL;
clks_exec_running_depth = 0U;
clks_exec_next_pid = 1ULL;
clks_exec_pid_stack_depth = 0U;
clks_memset(clks_exec_pid_stack, 0, sizeof(clks_exec_pid_stack));
clks_memset(clks_exec_exit_requested_stack, 0, sizeof(clks_exec_exit_requested_stack));
clks_memset(clks_exec_exit_status_stack, 0, sizeof(clks_exec_exit_status_stack));
clks_memset(clks_exec_proc_table, 0, sizeof(clks_exec_proc_table));
clks_log(CLKS_LOG_INFO, "EXEC", "PATH EXEC FRAMEWORK ONLINE");
}
clks_bool clks_exec_run_path(const char *path, u64 *out_status) {
return clks_exec_run_path_internal(path, out_status, CLKS_NULL);
}
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);
}
u64 clks_exec_wait_pid(u64 pid, u64 *out_status) {
i32 slot;
const struct clks_exec_proc_record *proc;
slot = clks_exec_proc_find_slot_by_pid(pid);
if (slot < 0) {
return (u64)-1;
}
proc = &clks_exec_proc_table[(u32)slot];
if (proc->state == CLKS_EXEC_PROC_RUNNING) {
return 0ULL;
}
if (out_status != CLKS_NULL) {
*out_status = proc->exit_status;
}
return 1ULL;
}
clks_bool clks_exec_request_exit(u64 status) {
i32 depth_index = clks_exec_current_depth_index();
if (depth_index < 0) {
return CLKS_FALSE;
}
clks_exec_exit_requested_stack[(u32)depth_index] = CLKS_TRUE;
clks_exec_exit_status_stack[(u32)depth_index] = status;
return CLKS_TRUE;
}
u64 clks_exec_current_pid(void) {
i32 depth_index = clks_exec_current_depth_index();
if (depth_index < 0) {
return 0ULL;
}
return clks_exec_pid_stack[(u32)depth_index];
}
u64 clks_exec_sleep_ticks(u64 ticks) {
u64 start = clks_interrupts_timer_ticks();
if (ticks == 0ULL) {
return 0ULL;
}
while ((clks_interrupts_timer_ticks() - start) < ticks) {
#if defined(CLKS_ARCH_X86_64)
__asm__ volatile("sti; hlt; cli" : : : "memory");
#elif defined(CLKS_ARCH_AARCH64)
clks_cpu_pause();
#endif
}
return clks_interrupts_timer_ticks() - start;
}
u64 clks_exec_yield(void) {
#if defined(CLKS_ARCH_X86_64)
__asm__ volatile("sti; hlt; cli" : : : "memory");
#elif defined(CLKS_ARCH_AARCH64)
clks_cpu_pause();
#endif
return clks_interrupts_timer_ticks();
} }
u64 clks_exec_request_count(void) { u64 clks_exec_request_count(void) {
@@ -142,4 +395,3 @@ u64 clks_exec_success_count(void) {
clks_bool clks_exec_is_running(void) { clks_bool clks_exec_is_running(void) {
return (clks_exec_running_depth > 0U) ? CLKS_TRUE : CLKS_FALSE; return (clks_exec_running_depth > 0U) ? CLKS_TRUE : CLKS_FALSE;
} }

View File

@@ -200,6 +200,48 @@ static u64 clks_syscall_exec_path(u64 arg0) {
return status; return status;
} }
static u64 clks_syscall_getpid(void) {
return clks_exec_current_pid();
}
static u64 clks_syscall_spawn_path(u64 arg0) {
char path[CLKS_SYSCALL_PATH_MAX];
u64 pid = (u64)-1;
if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) {
return (u64)-1;
}
if (clks_exec_spawn_path(path, &pid) == CLKS_FALSE) {
return (u64)-1;
}
return pid;
}
static u64 clks_syscall_waitpid(u64 arg0, u64 arg1) {
u64 status = (u64)-1;
u64 wait_ret = clks_exec_wait_pid(arg0, &status);
if (wait_ret == 1ULL && arg1 != 0ULL) {
clks_memcpy((void *)arg1, &status, sizeof(status));
}
return wait_ret;
}
static u64 clks_syscall_exit(u64 arg0) {
return (clks_exec_request_exit(arg0) == CLKS_TRUE) ? 1ULL : 0ULL;
}
static u64 clks_syscall_sleep_ticks(u64 arg0) {
return clks_exec_sleep_ticks(arg0);
}
static u64 clks_syscall_yield(void) {
return clks_exec_yield();
}
static u64 clks_syscall_fs_stat_type(u64 arg0) { static u64 clks_syscall_fs_stat_type(u64 arg0) {
char path[CLKS_SYSCALL_PATH_MAX]; char path[CLKS_SYSCALL_PATH_MAX];
struct clks_fs_node_info info; struct clks_fs_node_info info;
@@ -436,6 +478,18 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
return clks_keyboard_drop_count(); return clks_keyboard_drop_count();
case CLKS_SYSCALL_KBD_HOTKEY_SWITCHES: case CLKS_SYSCALL_KBD_HOTKEY_SWITCHES:
return clks_keyboard_hotkey_switch_count(); return clks_keyboard_hotkey_switch_count();
case CLKS_SYSCALL_GETPID:
return clks_syscall_getpid();
case CLKS_SYSCALL_SPAWN_PATH:
return clks_syscall_spawn_path(frame->rbx);
case CLKS_SYSCALL_WAITPID:
return clks_syscall_waitpid(frame->rbx, frame->rcx);
case CLKS_SYSCALL_EXIT:
return clks_syscall_exit(frame->rbx);
case CLKS_SYSCALL_SLEEP_TICKS:
return clks_syscall_sleep_ticks(frame->rbx);
case CLKS_SYSCALL_YIELD:
return clks_syscall_yield();
default: default:
return (u64)-1; return (u64)-1;
} }

View File

@@ -52,7 +52,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `FS_MKDIR` / `FS_WRITE` / `FS_APPEND` / `FS_REMOVE` 仅允许 `/temp` 树下路径。 - `FS_MKDIR` / `FS_WRITE` / `FS_APPEND` / `FS_REMOVE` 仅允许 `/temp` 树下路径。
## 4. Syscall 列表0~39 ## 4. Syscall 列表0~45
### 0 `CLEONOS_SYSCALL_LOG_WRITE` ### 0 `CLEONOS_SYSCALL_LOG_WRITE`
@@ -294,6 +294,50 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- 参数:无 - 参数:无
- 返回ALT+F1..F4 热键切换计数 - 返回ALT+F1..F4 热键切换计数
### 40 `CLEONOS_SYSCALL_GETPID`
- 参数:无
- 返回:当前进程 PID无活动进程时为 `0`
### 41 `CLEONOS_SYSCALL_SPAWN_PATH`
- 参数:
- `arg0`: `const char *path`
- 返回:
- 成功:子进程 PID
- 失败:`-1`
- 说明:当前 Stage27 为同步 spawn内部会执行完成后再返回 PID
### 42 `CLEONOS_SYSCALL_WAITPID`
- 参数:
- `arg0`: `u64 pid`
- `arg1`: `u64 *out_status`(可为 `0`
- 返回:
- `-1`PID 不存在
- `0`:目标进程仍在运行
- `1`:目标进程已退出
- 说明:当返回 `1``arg1!=0` 时,会写入退出码。
### 43 `CLEONOS_SYSCALL_EXIT`
- 参数:
- `arg0`: `u64 status`
- 返回:
- `1`:已记录退出请求
- `0`:当前上下文不支持退出请求
### 44 `CLEONOS_SYSCALL_SLEEP_TICKS`
- 参数:
- `arg0`: `u64 ticks`
- 返回:实际休眠 tick 数
### 45 `CLEONOS_SYSCALL_YIELD`
- 参数:无
- 返回:当前 tick
## 5. 用户态封装函数 ## 5. 用户态封装函数
用户态封装位于: 用户态封装位于:
@@ -308,9 +352,11 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `cleonos_sys_exec_path()` - `cleonos_sys_exec_path()`
- `cleonos_sys_tty_write()` - `cleonos_sys_tty_write()`
- `cleonos_sys_kbd_get_char()` / `cleonos_sys_kbd_buffered()` - `cleonos_sys_kbd_get_char()` / `cleonos_sys_kbd_buffered()`
- `cleonos_sys_getpid()` / `cleonos_sys_spawn_path()` / `cleonos_sys_wait_pid()`
- `cleonos_sys_exit()` / `cleonos_sys_sleep_ticks()` / `cleonos_sys_yield()`
## 6. 开发注意事项 ## 6. 开发注意事项
- 传入的字符串/缓冲指针目前按“同地址空间可直接访问”模型处理,后续若引入严格用户态地址隔离,需要补充用户内存校验。 - 传入的字符串/缓冲指针目前按“同地址空间可直接访问”模型处理,后续若引入严格用户态地址隔离,需要补充用户内存校验。
- `FS_READ` 不保证文本终止符;读取文本请预留 1 字节并手动 `buf[n] = '\0'` - `FS_READ` 不保证文本终止符;读取文本请预留 1 字节并手动 `buf[n] = '\0'`
- `FS_WRITE`/`FS_APPEND` 仅允许 `/temp`,并有单次长度上限。 - `FS_WRITE`/`FS_APPEND` 仅允许 `/temp`,并有单次长度上限。`n

View File

@@ -37,14 +37,15 @@ python wine/cleonos_wine.py build/x86_64/ramdisk_root/shell/shell.elf --rootfs b
## 支持 ## 支持
- ELF64 (x86_64) PT_LOAD 段装载 - ELF64 (x86_64) PT_LOAD 段装载
- CLeonOS `int 0x80` syscall 0..39 - CLeonOS `int 0x80` syscall 0..45
- TTY 输出与键盘输入队列 - TTY 输出与键盘输入队列
- rootfs 文件/目录访问(`FS_*` - rootfs 文件/目录访问(`FS_*`
- `/temp` 写入限制(`FS_MKDIR/WRITE/APPEND/REMOVE` - `/temp` 写入限制(`FS_MKDIR/WRITE/APPEND/REMOVE`
- `EXEC_PATH` 递归执行 ELF带深度限制 - `EXEC_PATH` 递归执行 ELF带深度限制
- 进程生命周期 syscall`GETPID/SPAWN_PATH/WAITPID/EXIT/SLEEP_TICKS/YIELD`
## 参数 ## 参数
- `--no-kbd`:关闭输入线程 - `--no-kbd`:关闭输入线程
- `--max-exec-depth N`:设置 exec 嵌套深度上限 - `--max-exec-depth N`:设置 exec 嵌套深度上限
- `--verbose`:打印更多日志 - `--verbose`:打印更多日志`n

View File

@@ -48,6 +48,12 @@ SYS_KBD_PUSHED = 36
SYS_KBD_POPPED = 37 SYS_KBD_POPPED = 37
SYS_KBD_DROPPED = 38 SYS_KBD_DROPPED = 38
SYS_KBD_HOTKEY_SWITCHES = 39 SYS_KBD_HOTKEY_SWITCHES = 39
SYS_GETPID = 40
SYS_SPAWN_PATH = 41
SYS_WAITPID = 42
SYS_EXIT = 43
SYS_SLEEP_TICKS = 44
SYS_YIELD = 45
def u64(value: int) -> int: def u64(value: int) -> int:
@@ -63,4 +69,4 @@ def page_floor(addr: int) -> int:
def page_ceil(addr: int) -> int: def page_ceil(addr: int) -> int:
return (addr + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1) return (addr + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)`n

View File

@@ -3,6 +3,7 @@ from __future__ import annotations
import os import os
import struct import struct
import sys import sys
import time
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
@@ -18,6 +19,12 @@ from .constants import (
SYS_EXEC_PATH, SYS_EXEC_PATH,
SYS_EXEC_REQUESTS, SYS_EXEC_REQUESTS,
SYS_EXEC_SUCCESS, SYS_EXEC_SUCCESS,
SYS_EXIT,
SYS_GETPID,
SYS_SLEEP_TICKS,
SYS_SPAWN_PATH,
SYS_WAITPID,
SYS_YIELD,
SYS_FS_APPEND, SYS_FS_APPEND,
SYS_FS_CHILD_COUNT, SYS_FS_CHILD_COUNT,
SYS_FS_GET_CHILD_NAME, SYS_FS_GET_CHILD_NAME,
@@ -107,6 +114,8 @@ class CLeonOSWineNative:
no_kbd: bool = False, no_kbd: bool = False,
verbose: bool = False, verbose: bool = False,
top_level: bool = True, top_level: bool = True,
pid: int = 0,
ppid: int = 0,
) -> None: ) -> None:
self.elf_path = elf_path self.elf_path = elf_path
self.rootfs = rootfs self.rootfs = rootfs
@@ -117,6 +126,10 @@ class CLeonOSWineNative:
self.no_kbd = no_kbd self.no_kbd = no_kbd
self.verbose = verbose self.verbose = verbose
self.top_level = top_level self.top_level = top_level
self.pid = int(pid)
self.ppid = int(ppid)
self._exit_requested = False
self._exit_status = 0
self.image = self._parse_elf(self.elf_path) self.image = self._parse_elf(self.elf_path)
self.exit_code: Optional[int] = None self.exit_code: Optional[int] = None
@@ -128,6 +141,12 @@ class CLeonOSWineNative:
self._mapped_ranges: List[Tuple[int, int]] = [] self._mapped_ranges: List[Tuple[int, int]] = []
def run(self) -> Optional[int]: def run(self) -> Optional[int]:
if self.pid == 0:
self.pid = self.state.alloc_pid(self.ppid)
prev_pid = self.state.get_current_pid()
self.state.set_current_pid(self.pid)
uc = Uc(UC_ARCH_X86, UC_MODE_64) uc = Uc(UC_ARCH_X86, UC_MODE_64)
self._install_hooks(uc) self._install_hooks(uc)
self._load_segments(uc) self._load_segments(uc)
@@ -137,24 +156,37 @@ class CLeonOSWineNative:
self._input_pump = InputPump(self.state) self._input_pump = InputPump(self.state)
self._input_pump.start() self._input_pump.start()
run_failed = False
try: try:
uc.emu_start(self.image.entry, 0) uc.emu_start(self.image.entry, 0)
except KeyboardInterrupt: except KeyboardInterrupt:
run_failed = True
if self.top_level: if self.top_level:
print("\n[WINE] interrupted by user", file=sys.stderr) print("\n[WINE] interrupted by user", file=sys.stderr)
return None
except UcError as exc: except UcError as exc:
run_failed = True
if self.verbose or self.top_level: if self.verbose or self.top_level:
print(f"[WINE][ERROR] runtime crashed: {exc}", file=sys.stderr) print(f"[WINE][ERROR] runtime crashed: {exc}", file=sys.stderr)
return None
finally: finally:
if self.top_level and self._input_pump is not None: if self.top_level and self._input_pump is not None:
self._input_pump.stop() self._input_pump.stop()
if run_failed:
self.state.mark_exited(self.pid, u64_neg1())
self.state.set_current_pid(prev_pid)
return None
if self.exit_code is None: if self.exit_code is None:
self.exit_code = self._reg_read(uc, UC_X86_REG_RAX) self.exit_code = self._reg_read(uc, UC_X86_REG_RAX)
return u64(self.exit_code) if self._exit_requested:
self.exit_code = self._exit_status
self.exit_code = u64(self.exit_code)
self.state.mark_exited(self.pid, self.exit_code)
self.state.set_current_pid(prev_pid)
return self.exit_code
def _install_hooks(self, uc: Uc) -> None: def _install_hooks(self, uc: Uc) -> None:
uc.hook_add(UC_HOOK_INTR, self._hook_intr) uc.hook_add(UC_HOOK_INTR, self._hook_intr)
@@ -212,6 +244,18 @@ class CLeonOSWineNative:
return self._fs_read(uc, arg0, arg1, arg2) return self._fs_read(uc, arg0, arg1, arg2)
if sid == SYS_EXEC_PATH: if sid == SYS_EXEC_PATH:
return self._exec_path(uc, arg0) return self._exec_path(uc, arg0)
if sid == SYS_SPAWN_PATH:
return self._spawn_path(uc, arg0)
if sid == SYS_WAITPID:
return self._wait_pid(uc, arg0, arg1)
if sid == SYS_GETPID:
return self.state.get_current_pid()
if sid == SYS_EXIT:
return self._request_exit(uc, arg0)
if sid == SYS_SLEEP_TICKS:
return self._sleep_ticks(arg0)
if sid == SYS_YIELD:
return self._yield_once()
if sid == SYS_EXEC_REQUESTS: if sid == SYS_EXEC_REQUESTS:
return self.state.exec_requests return self.state.exec_requests
if sid == SYS_EXEC_SUCCESS: if sid == SYS_EXEC_SUCCESS:
@@ -618,6 +662,12 @@ class CLeonOSWineNative:
return 1 if self._write_guest_bytes(uc, out_ptr, encoded + b"\x00") else 0 return 1 if self._write_guest_bytes(uc, out_ptr, encoded + b"\x00") else 0
def _exec_path(self, uc: Uc, path_ptr: int) -> int: def _exec_path(self, uc: Uc, path_ptr: int) -> int:
return self._spawn_path_common(uc, path_ptr, return_pid=False)
def _spawn_path(self, uc: Uc, path_ptr: int) -> int:
return self._spawn_path_common(uc, path_ptr, return_pid=True)
def _spawn_path_common(self, uc: Uc, path_ptr: int, *, return_pid: bool) -> int:
path = self._read_guest_cstring(uc, path_ptr) path = self._read_guest_cstring(uc, path_ptr)
guest_path = self._normalize_guest_path(path) guest_path = self._normalize_guest_path(path)
host_path = self._guest_to_host(guest_path, must_exist=True) host_path = self._guest_to_host(guest_path, must_exist=True)
@@ -635,6 +685,9 @@ class CLeonOSWineNative:
self.state.user_launch_fail = u64(self.state.user_launch_fail + 1) self.state.user_launch_fail = u64(self.state.user_launch_fail + 1)
return u64_neg1() return u64_neg1()
parent_pid = self.state.get_current_pid()
child_pid = self.state.alloc_pid(parent_pid)
child = CLeonOSWineNative( child = CLeonOSWineNative(
elf_path=host_path, elf_path=host_path,
rootfs=self.rootfs, rootfs=self.rootfs,
@@ -645,18 +698,57 @@ class CLeonOSWineNative:
no_kbd=True, no_kbd=True,
verbose=self.verbose, verbose=self.verbose,
top_level=False, top_level=False,
pid=child_pid,
ppid=parent_pid,
) )
child_ret = child.run() child_ret = child.run()
if child_ret is None: if child_ret is None:
self.state.user_launch_fail = u64(self.state.user_launch_fail + 1) self.state.user_launch_fail = u64(self.state.user_launch_fail + 1)
return u64_neg1() return u64_neg1()
self.state.exec_success = u64(self.state.exec_success + 1) self.state.exec_success = u64(self.state.exec_success + 1)
self.state.user_launch_ok = u64(self.state.user_launch_ok + 1) self.state.user_launch_ok = u64(self.state.user_launch_ok + 1)
if guest_path.lower().startswith("/system/"): if guest_path.lower().startswith("/system/"):
self.state.kelf_runs = u64(self.state.kelf_runs + 1) self.state.kelf_runs = u64(self.state.kelf_runs + 1)
if return_pid:
return child_pid
return 0 return 0
def _wait_pid(self, uc: Uc, pid: int, out_ptr: int) -> int:
wait_ret, status = self.state.wait_pid(int(pid))
if wait_ret == 1 and out_ptr != 0:
self._write_guest_bytes(uc, out_ptr, struct.pack("<Q", u64(status)))
return int(wait_ret)
def _request_exit(self, uc: Uc, status: int) -> int:
self._exit_requested = True
self._exit_status = u64(status)
uc.emu_stop()
return 1
def _sleep_ticks(self, ticks: int) -> int:
ticks = int(u64(ticks))
if ticks == 0:
return 0
start = self.state.timer_ticks()
while (self.state.timer_ticks() - start) < ticks:
time.sleep(0.001)
return self.state.timer_ticks() - start
def _yield_once(self) -> int:
time.sleep(0)
return self.state.timer_ticks()
def _guest_to_host(self, guest_path: str, *, must_exist: bool) -> Optional[Path]: def _guest_to_host(self, guest_path: str, *, must_exist: bool) -> Optional[Path]:
norm = self._normalize_guest_path(guest_path) norm = self._normalize_guest_path(guest_path)
if norm == "/": if norm == "/":
@@ -782,4 +874,4 @@ def resolve_elf_target(elf_arg: str, rootfs: Path) -> Tuple[Path, str]:
host_path = _guest_to_host_for_resolve(rootfs, guest_path) host_path = _guest_to_host_for_resolve(rootfs, guest_path)
if host_path is None: if host_path is None:
raise FileNotFoundError(f"ELF not found as host path or guest path: {elf_arg}") raise FileNotFoundError(f"ELF not found as host path or guest path: {elf_arg}")
return host_path.resolve(), guest_path return host_path.resolve(), guest_path`n

View File

@@ -4,7 +4,7 @@ import collections
import threading import threading
import time import time
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Deque, Optional from typing import Deque, Dict, Optional, Tuple
from .constants import u64 from .constants import u64
@@ -39,6 +39,12 @@ class SharedKernelState:
log_journal: Deque[str] = field(default_factory=lambda: collections.deque(maxlen=256)) log_journal: Deque[str] = field(default_factory=lambda: collections.deque(maxlen=256))
fs_write_max: int = 65536 fs_write_max: int = 65536
proc_lock: threading.Lock = field(default_factory=threading.Lock)
proc_next_pid: int = 1
proc_current_pid: int = 0
proc_parents: Dict[int, int] = field(default_factory=dict)
proc_status: Dict[int, Optional[int]] = field(default_factory=dict)
def timer_ticks(self) -> int: def timer_ticks(self) -> int:
return (time.monotonic_ns() - self.start_ns) // 1_000_000 return (time.monotonic_ns() - self.start_ns) // 1_000_000
@@ -80,3 +86,46 @@ class SharedKernelState:
if index_from_oldest < 0 or index_from_oldest >= len(self.log_journal): if index_from_oldest < 0 or index_from_oldest >= len(self.log_journal):
return None return None
return list(self.log_journal)[index_from_oldest] return list(self.log_journal)[index_from_oldest]
def alloc_pid(self, ppid: int) -> int:
with self.proc_lock:
pid = int(self.proc_next_pid)
if pid == 0:
pid = 1
self.proc_next_pid = int(u64(pid + 1))
if self.proc_next_pid == 0:
self.proc_next_pid = 1
self.proc_parents[pid] = int(ppid)
self.proc_status[pid] = None
return pid
def set_current_pid(self, pid: int) -> None:
with self.proc_lock:
self.proc_current_pid = int(pid)
def get_current_pid(self) -> int:
with self.proc_lock:
return int(self.proc_current_pid)
def mark_exited(self, pid: int, status: int) -> None:
if pid <= 0:
return
with self.proc_lock:
self.proc_status[int(pid)] = int(u64(status))
def wait_pid(self, pid: int) -> Tuple[int, int]:
with self.proc_lock:
if pid not in self.proc_status:
return int(u64(-1)), 0
status = self.proc_status[pid]
if status is None:
return 0, 0
return 1, int(status)`n