diff --git a/ce/interp.c b/ce/interp.c index 1ba59ba..d02a502 100644 --- a/ce/interp.c +++ b/ce/interp.c @@ -340,7 +340,7 @@ static void help (struct context* context) { } static void cmd_cancel_proc (void* arg) { - int pid = (int)arg; + int pid = (int)(uintptr_t)arg; char ch = 0; do { @@ -350,6 +350,18 @@ static void cmd_cancel_proc (void* arg) { kill (pid); } +static void cmd_collect_proc (void* arg) { +#define RECV_MAX (1024 * 16) + + for (;;) { + char recv[RECV_MAX]; + memset (recv, 0, sizeof (recv)); + mail_receive (&recv, sizeof (recv) - 1); + + mail_send (e_pgid, recv, strlen (recv)); + } +} + static void execute_cmd (struct ast_cmd* cmd, struct context* context) { if (strcmp (cmd->name, "echo") == 0) { echo (context, cmd->args, cmd->arg_count); @@ -398,19 +410,40 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context) { return; } - int pid = exec (volume, path); + int pid = exec_partial (volume, path); if (pid < 0) { cprintf (context, "ERROR could not run '%s': %s\n", cmd->name, str_status[-pid]); return; } + for (int i = 0; i < cmd->arg_count; i++) { + char* arg = cmd->args[i]; + char *key, *value; + + char* sep = strchr (arg, '='); + + if (sep != NULL) { + *sep = '\0'; + + key = arg; + value = sep + 1; + + env_set (pid, key, value, strlen (value) + 1); + } + } + + exec_partial_fini (pid); + struct process_data* cancel_pdata = process_spawn (&cmd_cancel_proc, (void*)pid); + struct process_data* collect_pdata = process_spawn (&cmd_collect_proc, NULL); wait_for_pid (pid); kill (cancel_pdata->pid); process_data_free (cancel_pdata); + kill (collect_pdata->pid); + process_data_free (collect_pdata); } } diff --git a/include/status.h b/include/status.h index bfebe2b..c46b714 100644 --- a/include/status.h +++ b/include/status.h @@ -25,5 +25,6 @@ #define ST_REMOVE_ERROR 21 #define ST_XDRV_READ_ERROR 22 #define ST_XDRV_WRITE_ERROR 23 +#define ST_NOT_PARTIAL 24 #endif // _M_STATUS_H diff --git a/include/syscall_defs.h b/include/syscall_defs.h index f5309ff..b34f830 100644 --- a/include/syscall_defs.h +++ b/include/syscall_defs.h @@ -32,5 +32,7 @@ #define SYS_CREATE_VOLUME 29 #define SYS_ENV_SET 30 #define SYS_ENV_GET 31 +#define SYS_EXEC_PARTIAL 32 +#define SYS_EXEC_PARTIAL_FINI 33 #endif // _M_SYSCALL_DEFS_H diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index a7277bd..ba05672 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -212,6 +212,18 @@ void proc_register (struct proc* proc, struct cpu* register_cpu, struct reschedu rctx_insert_cpu (rctx, cpu); } +void proc_register_partial (struct proc* proc) { + uint64_t fpt, fp; + + spin_lock (&proc_tree_lock, &fpt); + spin_lock (&proc->lock, &fp); + + rbtree_insert (struct proc, &proc_tree, &proc->proc_tree_link, proc_tree_link, pid); + + spin_unlock (&proc->lock, fp); + spin_unlock (&proc_tree_lock, fpt); +} + /* caller holds cpu->lock */ static struct proc* proc_find_sched (struct cpu* cpu) { uint64_t fp; diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index 19c9d90..54b0f67 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -22,6 +22,7 @@ /* process states */ #define PROC_READY 0 #define PROC_SUSPENDED 1 +#define PROC_PARTIAL 2 /* process flags */ #define PROC_USTK_PREALLOC (1 << 0) @@ -61,6 +62,8 @@ struct elf_aux proc_load_segments (struct proc* proc, uint8_t* elf); void proc_register (struct proc* proc, struct cpu* register_cpu, struct reschedule_ctx* rctx); +void proc_register_partial (struct proc* proc); + struct proc* proc_find_pid (int pid); struct proc* proc_from_file (struct proc* proc1, const char* volume, const char* path, diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 8bc2880..60f7c81 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -396,6 +396,101 @@ DEFINE_SYSCALL (sys_exec) { return SYSRESULT (pid); } +/* int exec_partial (char* volume, char* path) */ +DEFINE_SYSCALL (sys_exec_partial) { + uint64_t fpg, fp; + + uintptr_t uvaddr_volume = a1; + uintptr_t uvaddr_path = a2; + + struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + + uintptr_t out_paddr; + + spin_lock (&proc->lock, &fp); + struct procgroup* procgroup = proc->procgroup; + int pid1 = proc->pid; + spin_unlock (&proc->lock, fp); + + spin_lock (&procgroup->lock, &fpg); + out_paddr = mm_v2p (&procgroup->pd, uvaddr_path); + spin_unlock (&procgroup->lock, fpg); + + if (out_paddr == 0) + return SYSRESULT (-ST_BAD_ADDRESS_SPACE); + + const char* path = (const char*)((uintptr_t)hhdm->offset + out_paddr); + + spin_lock (&procgroup->lock, &fpg); + + out_paddr = mm_v2p (&procgroup->pd, uvaddr_volume); + + if (out_paddr == 0) { + spin_unlock (&procgroup->lock, fpg); + return SYSRESULT (-ST_BAD_ADDRESS_SPACE); + } + + const char* volume = (const char*)((uintptr_t)hhdm->offset + out_paddr); + + struct proc* new = proc_from_file (proc, volume, path, rctx); + + if (new == NULL) { + spin_unlock (&procgroup->lock, fpg); + return SYSRESULT (-ST_EXEC_ERROR); + } + + spin_unlock (&procgroup->lock, fpg); + + int pid = new->pid; + new->exec_pid = pid1; + new->state = PROC_PARTIAL; + + proc_register_partial (new); + + return SYSRESULT (pid); +} + +/* int exec_partial_fini (int pid) */ +DEFINE_SYSCALL (sys_exec_partial_fini) { + uint64_t fp, fc; + + int pid = (int)a1; + + struct proc* target_proc = proc_find_pid (pid); + + if (target_proc == NULL) + return SYSRESULT (-ST_NOT_FOUND); + + spin_lock (&target_proc->lock, &fp); + + if (target_proc->state != PROC_PARTIAL) { + spin_unlock (&target_proc->lock, fp); + return SYSRESULT (-ST_NOT_PARTIAL); + } + + spin_unlock (&target_proc->lock, fp); + + struct cpu* cpu = cpu_find_lightest (); + + spin_lock (&cpu->lock, &fc); + spin_lock (&target_proc->lock, &fp); + + target_proc->cpu = cpu; + target_proc->state = PROC_READY; + + cpu->proc_run_q_count++; + list_append (cpu->proc_run_q, &target_proc->cpu_run_q_link); + if (cpu->proc_current == NULL) + cpu->proc_current = target_proc; + + spin_unlock (&target_proc->lock, fp); + spin_unlock (&cpu->lock, fc); + + rctx_insert_cpu (rctx, cpu); + + return SYSRESULT (ST_OK); +} + /* int volume_open (char* volume) */ DEFINE_SYSCALL (sys_volume_open) { uint64_t fpg, fp; @@ -688,8 +783,6 @@ DEFINE_SYSCALL (sys_wait_for_pid) { /* int kill (int pid) */ DEFINE_SYSCALL (sys_kill) { - uint64_t fp; - int pid = (int)a1; struct proc* target_proc = proc_find_pid (pid); @@ -810,21 +903,28 @@ DEFINE_SYSCALL (sys_create_volume) { return SYSRESULT (vfs_create_volume (proc, rctx, key, type, device, false)); } -/* int env_set (char* key, void* buffer, size_t size) */ +/* int env_set (int pid, char* key, void* buffer, size_t size) */ DEFINE_SYSCALL (sys_env_set) { uint64_t fp, fpg; - uintptr_t uvaddr_key = a1; - uintptr_t uvaddr_buffer = a2; - size_t size = (size_t)a3; + int pid = (int)a1; + uintptr_t uvaddr_key = a2; + uintptr_t uvaddr_buffer = a3; + size_t size = (size_t)a4; struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + struct proc* target_proc = proc_find_pid (pid); + + if (target_proc == NULL) { + return SYSRESULT (-ST_NOT_FOUND); + } + uintptr_t out_paddr; - spin_lock (&proc->lock, &fp); - struct procgroup* procgroup = proc->procgroup; - spin_unlock (&proc->lock, fp); + spin_lock (&target_proc->lock, &fp); + struct procgroup* procgroup = target_proc->procgroup; + spin_unlock (&target_proc->lock, fp); spin_lock (&procgroup->lock, &fpg); @@ -844,24 +944,31 @@ DEFINE_SYSCALL (sys_env_set) { if (buffer == NULL) return SYSRESULT (-ST_BAD_ADDRESS_SPACE); - return SYSRESULT (proc_env_set (proc, key, buffer, size)); + return SYSRESULT (proc_env_set (target_proc, key, buffer, size)); } -/* int env_get (char* key, void* buffer, size_t size) */ +/* int env_get (int pid, char* key, void* buffer, size_t size) */ DEFINE_SYSCALL (sys_env_get) { uint64_t fp, fpg; - uintptr_t uvaddr_key = a1; - uintptr_t uvaddr_buffer = a2; - size_t size = (size_t)a3; + int pid = (int)a1; + uintptr_t uvaddr_key = a2; + uintptr_t uvaddr_buffer = a3; + size_t size = (size_t)a4; struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + struct proc* target_proc = proc_find_pid (pid); + + if (target_proc == NULL) { + return SYSRESULT (-ST_NOT_FOUND); + } + uintptr_t out_paddr; - spin_lock (&proc->lock, &fp); - struct procgroup* procgroup = proc->procgroup; - spin_unlock (&proc->lock, fp); + spin_lock (&target_proc->lock, &fp); + struct procgroup* procgroup = target_proc->procgroup; + spin_unlock (&target_proc->lock, fp); spin_lock (&procgroup->lock, &fpg); @@ -881,7 +988,7 @@ DEFINE_SYSCALL (sys_env_get) { if (buffer == NULL) return SYSRESULT (-ST_BAD_ADDRESS_SPACE); - return SYSRESULT (proc_env_set (proc, key, buffer, size)); + return SYSRESULT (proc_env_set (target_proc, key, buffer, size)); } static syscall_handler_func_t handler_table[] = { @@ -916,6 +1023,8 @@ static syscall_handler_func_t handler_table[] = { [SYS_CREATE_VOLUME] = &sys_create_volume, [SYS_ENV_SET] = &sys_env_set, [SYS_ENV_GET] = &sys_env_get, + [SYS_EXEC_PARTIAL] = &sys_exec_partial, + [SYS_EXEC_PARTIAL_FINI] = &sys_exec_partial_fini, }; syscall_handler_func_t syscall_find_handler (int syscall_num) { diff --git a/libsystem/str_status.h b/libsystem/str_status.h index 8f591ec..ed40fe6 100644 --- a/libsystem/str_status.h +++ b/libsystem/str_status.h @@ -28,6 +28,7 @@ static const char* str_status[] = { [ST_REMOVE_ERROR] = "remove error", [ST_XDRV_READ_ERROR] = "drive read error", [ST_XDRV_WRITE_ERROR] = "drive write error", + [ST_NOT_PARTIAL] = "not a partially created process", }; #endif // _LIBSYSTEM_STR_STATUS_H diff --git a/libsystem/system.c b/libsystem/system.c index ffd3c47..3a1aeb8 100644 --- a/libsystem/system.c +++ b/libsystem/system.c @@ -87,10 +87,16 @@ int create_volume (const char* key, int fs_type, const char* device_key) { return (int)do_syscall (SYS_CREATE_VOLUME, key, fs_type, device_key); } -int env_set (const char* key, void* buffer, size_t len) { - return (int)do_syscall (SYS_ENV_SET, key, buffer, len); +int env_set (int pid, const char* key, void* buffer, size_t len) { + return (int)do_syscall (SYS_ENV_SET, pid, key, buffer, len); } -int env_get (const char* key, void* buffer, size_t len) { - return (int)do_syscall (SYS_ENV_GET, key, buffer, len); +int env_get (int pid, const char* key, void* buffer, size_t len) { + return (int)do_syscall (SYS_ENV_GET, pid, key, buffer, len); } + +int exec_partial (const char* volume, const char* path) { + return (int)do_syscall (SYS_EXEC_PARTIAL, volume, path); +} + +int exec_partial_fini (int pid) { return (int)do_syscall (SYS_EXEC_PARTIAL_FINI, pid); } diff --git a/libsystem/system.h b/libsystem/system.h index 18c525c..d9dc998 100644 --- a/libsystem/system.h +++ b/libsystem/system.h @@ -94,9 +94,15 @@ int remove (const char* path); int create_volume (const char* key, int fs_type, const char* device_key); /* Set environment variable */ -int env_set (const char* key, void* buffer, size_t len); +int env_set (int pid, const char* key, void* buffer, size_t len); /* Get environment variable */ -int env_get (const char* key, void* buffer, size_t len); +int env_get (int pid, const char* key, void* buffer, size_t len); + +/* Prepare process for execution */ +int exec_partial (const char* volume, const char* path); + +/* Finish process for execution - run it! */ +int exec_partial_fini (int pid); #endif // _LIBMSL_M_SYSTEM_H