From 9043c4f9ec0adabad5a8be1087ad8e5a7c31ee3e Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Sun, 1 Mar 2026 22:59:04 +0100 Subject: [PATCH] Implement waiting for process, CE add command cancelation, rctx many cpus --- LICENSE.txt | 22 +++---- aux/qemu_amd64.sh | 2 +- ce/ce.c | 117 +++++++++++++++++++++++++++---------- include/syscall_defs.h | 2 + init/init.c | 13 +++-- kernel/amd64/bootmain.c | 2 - kernel/amd64/intr.c | 29 +++++++-- kernel/amd64/proc.c | 20 +++++++ kernel/amd64/smp.c | 4 +- kernel/amd64/syscall.c | 15 ++++- kernel/proc/mutex.c | 2 + kernel/proc/proc.c | 37 +++++++----- kernel/proc/proc.h | 3 + kernel/proc/reschedule.h | 20 ++++++- kernel/proc/suspension_q.c | 12 ++-- kernel/syscall/syscall.c | 87 +++++++++++++++++++++++++-- libsystem/system.c | 4 ++ libsystem/system.h | 6 ++ 18 files changed, 308 insertions(+), 89 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 6cb808e..a5771de 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,11 +1,11 @@ -Copyright 2026 Kamil Kowalczyk - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Copyright 2026 Kamil Kowalczyk + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/aux/qemu_amd64.sh b/aux/qemu_amd64.sh index cca9eab..e229c5f 100755 --- a/aux/qemu_amd64.sh +++ b/aux/qemu_amd64.sh @@ -2,4 +2,4 @@ set -x -qemu-system-x86_64 -M q35 -m 4G -serial stdio -enable-kvm -cdrom mop3.iso -smp 4 $@ +qemu-system-x86_64 -M q35 -m 4G -serial stdio -enable-kvm -cdrom mop3.iso -smp 1 $@ diff --git a/ce/ce.c b/ce/ce.c index 60eb143..1a4a670 100644 --- a/ce/ce.c +++ b/ce/ce.c @@ -14,6 +14,9 @@ #include #include +#define CTRL(x) ((x) - '@') +#define CPRINTF_BUF_MAX (1024 * 16) + static struct arena arena; struct strbuf { @@ -45,8 +48,6 @@ struct context { struct strbuf strbuf; }; -#define CPRINTF_BUF_MAX 4096 - void cprintf (struct context* context, const char* fmt, ...) { va_list args; va_start (args, fmt); @@ -264,8 +265,26 @@ static int e_pgid; static bool run = true; -static void putch (char ch) { mail_send (e_pgid, &ch, 1); } -void putchar_ (char ch) { putch (ch); } +void putchar_ (char ch) { (void)ch; } + +void mprintf (const char* fmt, ...) { + va_list args; + va_start (args, fmt); + + char* buf = malloc (CPRINTF_BUF_MAX); + + if (buf == NULL) { + va_end (args); + return; + } + + int len = vsnprintf (buf, CPRINTF_BUF_MAX, fmt, args); + + va_end (args); + + mail_send (e_pgid, buf, len); + free (buf); +} static void tokenize (struct list_node_link** tokens, const char* text) { const char* p = text; @@ -311,7 +330,7 @@ static void tokenize (struct list_node_link** tokens, const char* text) { continue; } - printf ("ERROR unknown character '%c'\n", *p); + mprintf ("ERROR unknown character '%c'\r\n", *p); p++; } } @@ -331,7 +350,7 @@ static void parse_and_execute (struct list_node_link* tokens) { execute (root, &context); if (context.strbuf.items != NULL) - printf ("%.*s", (int)context.strbuf.count, context.strbuf.items); + mprintf ("%.*s", (int)context.strbuf.count, context.strbuf.items); } } } @@ -350,12 +369,12 @@ static void mkfile (struct context* context, char** file_paths, size_t files_cou const char* file_path = file_paths[i]; if (!path_parse (file_path, volume, &path)) { - cprintf (context, "ERROR bad path '%s'\n", file_path); + cprintf (context, "ERROR bad path '%s'\r\n", file_path); continue; } if ((ret = volume_open (volume)) < 0) { - cprintf (context, "ERROR could not open volume '%s': %s\n", volume, str_status[-ret]); + cprintf (context, "ERROR could not open volume '%s': %s\r\n", volume, str_status[-ret]); continue; } @@ -375,12 +394,12 @@ static void cat (struct context* context, char** file_paths, size_t files_count) const char* file_path = file_paths[i]; if (!path_parse (file_path, volume, &path)) { - cprintf (context, "ERROR bad path '%s'\n", file_path); + cprintf (context, "ERROR bad path '%s'\r\n", file_path); continue; } if ((ret = volume_open (volume)) < 0) { - cprintf (context, "ERROR could not open volume '%s': %s\n", volume, str_status[-ret]); + cprintf (context, "ERROR could not open volume '%s': %s\r\n", volume, str_status[-ret]); continue; } @@ -396,7 +415,7 @@ static void cat (struct context* context, char** file_paths, size_t files_count) memset (buffer, 0, desc.size + 1); read_file (path, 0, (uint8_t*)buffer, desc.size); - cprintf (context, "%s\n", buffer); + cprintf (context, "%s\r\n", buffer); close: if (buffer != NULL) @@ -413,26 +432,26 @@ static void ls (struct context* context, const char* path_string) { struct dir_entry entry; if (!path_parse (path_string, volume, &path)) { - cprintf (context, "ERROR bad path '%s'\n", path_string); + cprintf (context, "ERROR bad path '%s'\r\n", path_string); return; } if ((ret = volume_open (volume)) < 0) { - cprintf (context, "ERROR could not open volume '%s': %s\n", volume, str_status[-ret]); + cprintf (context, "ERROR could not open volume '%s': %s\r\n", volume, str_status[-ret]); return; } describe (path, &desc); if (desc.type != FS_DIR) { - cprintf (context, "ERROR '%s' is not a directory\n", path_string); + cprintf (context, "ERROR '%s' is not a directory\r\n", path_string); volume_close (); return; } size_t entries = desc.size; - cprintf (context, "total entries: %zu\n", entries); - cprintf (context, "\n"); + cprintf (context, "total entries: %zu\r\n", entries); + cprintf (context, "\r\n"); for (size_t entry_num = 0; entry_num < entries; entry_num++) { memset (&desc, 0, sizeof (desc)); @@ -441,7 +460,7 @@ static void ls (struct context* context, const char* path_string) { read_dir_entry (path, &entry, entry_num); describe (entry.path, &desc); - cprintf (context, "%c %-40s %-40zu\n", (desc.type == FS_DIR ? 'D' : 'F'), entry.path, + cprintf (context, "%c %-40s %-40zu\r\n", (desc.type == FS_DIR ? 'D' : 'F'), entry.path, desc.size); } @@ -450,17 +469,33 @@ static void ls (struct context* context, const char* path_string) { static void quit1 (struct context* context) { run = false; - cprintf (context, "Goodbye!\n"); + cprintf (context, "Goodbye!\r\n"); } static void help (struct context* context) { - cprintf (context, "Available commands:\n"); - cprintf (context, "echo ...\n"); - cprintf (context, "help\n"); - cprintf (context, "cat \n"); - cprintf (context, "ls \n"); - cprintf (context, "mkfile \n"); - cprintf (context, "quit\n"); + cprintf (context, "Available commands:\r\n"); + cprintf (context, "echo ...\r\n"); + cprintf (context, "help\r\n"); + cprintf (context, "cat \r\n"); + cprintf (context, "ls \r\n"); + cprintf (context, "mkfile \r\n"); + cprintf (context, "quit\r\n"); +} + +static void cmd_cancel_proc (void) { + int pid = *(int*)argument_ptr (); + + char ch = 0; + for (;;) { + mail_receive (&ch, 1); + + if (ch == CTRL ('C')) + break; + } + + kill (pid); + + quit (); } static void execute_cmd (struct ast_cmd* cmd, struct context* context) { @@ -477,7 +512,27 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context) { } else if (strcmp (cmd->name, "mkfile") == 0) { mkfile (context, cmd->args, cmd->arg_count); } else { - cprintf (context, "ERROR unknown command '%s'\n", cmd->name); + /* cprintf (context, "ERROR unknown command '%s'\r\n", cmd->name); */ + char volume[VOLUME_MAX]; + const char* path; + + if (!(path_parse (cmd->name, volume, &path))) { + cprintf (context, "ERROR bad path '%s'\r\n", cmd->name); + return; + } + + int pid = exec (volume, path); + + if (pid < 0) { + cprintf (context, "ERROR could not run '%s': %s\r\n", cmd->name, str_status[-pid]); + return; + } + + int cancel_pid = process_spawn (&cmd_cancel_proc, &pid); + + wait_for_pid (pid); + + kill (cancel_pid); } } @@ -487,12 +542,12 @@ static void execute_redir (struct ast_redir* redir, struct context* context) { int ret; if (!(path_parse (redir->file_path, volume, &path))) { - cprintf (context, "ERROR bad path '%s'\n", redir->file_path); + cprintf (context, "ERROR bad path '%s'\r\n", redir->file_path); return; } if ((ret = volume_open (volume)) < 0) { - cprintf (context, "ERROR could not open volume '%s': %s\n", volume, str_status[-ret]); + cprintf (context, "ERROR could not open volume '%s': %s\r\n", volume, str_status[-ret]); return; } @@ -543,7 +598,7 @@ void app_main (void) { memset (line_buffer, 0, sizeof (line_buffer)); while (run) { - printf (PROMPT); + mprintf (PROMPT); char ch = 0; for (;;) { @@ -554,11 +609,11 @@ void app_main (void) { if (line_cursor < LINE_BUFFER_MAX) { line_buffer[line_cursor++] = ch; - printf ("%c", ch); + mprintf ("%c", ch); } } - printf ("\n"); + mprintf ("\r\n"); exec_line (line_buffer); line_cursor = 0; diff --git a/include/syscall_defs.h b/include/syscall_defs.h index dd41c28..e687a1a 100644 --- a/include/syscall_defs.h +++ b/include/syscall_defs.h @@ -25,5 +25,7 @@ #define SYS_READ_DIR_ENTRY 22 #define SYS_CREATE_FILE 23 #define SYS_WRITE_FILE 24 +#define SYS_WAIT_FOR_PID 25 +#define SYS_KILL 26 #endif // _M_SYSCALL_DEFS_H diff --git a/init/init.c b/init/init.c index b71c5a1..eda9f2e 100644 --- a/init/init.c +++ b/init/init.c @@ -6,16 +6,17 @@ #include #include +#define RECV_MAX (1024 * 16) + static int ce_pgid; void receiver (void) { for (;;) { - char rcv; - mail_receive (&rcv, 1); - if (rcv == '\n') - terminal_print ("\r\n", 2); - else - terminal_print (&rcv, 1); + char recv[RECV_MAX]; + memset (recv, 0, sizeof (recv)); + mail_receive (&recv, sizeof (recv) - 1); + + terminal_print (recv, strlen (recv)); } } diff --git a/kernel/amd64/bootmain.c b/kernel/amd64/bootmain.c index 3681eeb..b1809af 100644 --- a/kernel/amd64/bootmain.c +++ b/kernel/amd64/bootmain.c @@ -56,8 +56,6 @@ void bootmain (void) { devices_init (); vfs_init (); - struct reschedule_ctx rctx = {.cpu = NULL, .reschedule = false}; - struct device* ramdisk = device_find ("RD"); vfs_create_volume ("RD", VFS_TARFS, ramdisk, false); diff --git a/kernel/amd64/intr.c b/kernel/amd64/intr.c index df18fa4..7ad534e 100644 --- a/kernel/amd64/intr.c +++ b/kernel/amd64/intr.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -160,11 +161,19 @@ static void intr_exception (struct saved_regs* regs) { regs->rbx); if (regs->cs == (GDT_UCODE | 0x03)) { - struct reschedule_ctx rctx = {.reschedule = false, .cpu = NULL}; + struct reschedule_ctx rctx = {0}; proc_kill (thiscpu->proc_current, &rctx); - if (rctx.reschedule) - cpu_request_sched (rctx.cpu); + bool do_thiscpu = false; + for (size_t i = 0; i < lengthof (rctx.cpus); i++) { + if (rctx.cpus[i] != NULL && rctx.cpus[i] != thiscpu) + cpu_request_sched (rctx.cpus[i]); + else + do_thiscpu = true; + } + + if (do_thiscpu) + cpu_request_sched (thiscpu); } else { __asm__ volatile ("cli"); spin (); @@ -196,11 +205,19 @@ void intr_handler (void* stack_ptr) { if (irq == NULL) return; - struct reschedule_ctx rctx = {.reschedule = false, .cpu = NULL}; + struct reschedule_ctx rctx = {0}; irq->func (irq->arg, stack_ptr, &rctx); - if (rctx.reschedule) - cpu_request_sched (rctx.cpu); + bool do_thiscpu = false; + for (size_t i = 0; i < lengthof (rctx.cpus); i++) { + if (rctx.cpus[i] != NULL && rctx.cpus[i] != thiscpu) + cpu_request_sched (rctx.cpus[i]); + else + do_thiscpu = true; + } + + if (do_thiscpu) + cpu_request_sched (thiscpu); } } diff --git a/kernel/amd64/proc.c b/kernel/amd64/proc.c index 1222b28..0ffd5ef 100644 --- a/kernel/amd64/proc.c +++ b/kernel/amd64/proc.c @@ -109,6 +109,26 @@ struct proc* proc_clone (struct proc* proto, uintptr_t vstack_top, uintptr_t ent } void proc_cleanup (struct proc* proc, struct reschedule_ctx* rctx) { + spin_lock (&proc->lock); + spin_lock (&proc->done_sq.lock); + + while (proc->done_sq.proc_list != NULL) { + struct list_node_link* node = proc->done_sq.proc_list; + struct proc_sq_entry* sq_entry = list_entry (node, struct proc_sq_entry, sq_link); + struct proc* suspended_proc = sq_entry->proc; + + spin_unlock (&proc->done_sq.lock); + spin_unlock (&proc->lock); + + proc_sq_resume (suspended_proc, sq_entry, rctx); + + spin_lock (&proc->lock); + spin_lock (&proc->done_sq.lock); + } + + spin_unlock (&proc->done_sq.lock); + spin_unlock (&proc->lock); + proc_sqs_cleanup (proc); proc_mutexes_cleanup (proc, rctx); diff --git a/kernel/amd64/smp.c b/kernel/amd64/smp.c index 0082285..5d15ea1 100644 --- a/kernel/amd64/smp.c +++ b/kernel/amd64/smp.c @@ -100,10 +100,10 @@ static void smp_bootstrap (struct limine_mp_info* mp_info) { atomic_fetch_sub (&cpu_counter, 1); - struct reschedule_ctx rctx = {.cpu = NULL, .reschedule = false}; + struct reschedule_ctx rctx = {0}; struct proc* spin_proc = proc_from_file (VFS_KERNEL, "RD", "/spin", &rctx); - proc_register (spin_proc, thiscpu, NULL); + proc_register (spin_proc, thiscpu, &rctx); spin_lock (&spin_proc->cpu->lock); do_sched (spin_proc, &spin_proc->cpu->lock); diff --git a/kernel/amd64/syscall.c b/kernel/amd64/syscall.c index ae3f5ca..f35ddb2 100644 --- a/kernel/amd64/syscall.c +++ b/kernel/amd64/syscall.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -37,7 +38,7 @@ uintptr_t syscall_dispatch (void* stack_ptr) { return -ST_SYSCALL_NOT_FOUND; } - struct reschedule_ctx rctx = {.reschedule = false, .cpu = NULL}; + struct reschedule_ctx rctx = {0}; uintptr_t r = func (caller, regs, &rctx, regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8, regs->r9); @@ -50,8 +51,16 @@ uintptr_t syscall_dispatch (void* stack_ptr) { spin_unlock (&caller->lock); } - if (rctx.reschedule) - cpu_request_sched (rctx.cpu); + bool do_thiscpu = false; + for (size_t i = 0; i < lengthof (rctx.cpus); i++) { + if (rctx.cpus[i] != NULL && rctx.cpus[i] != thiscpu) + cpu_request_sched (rctx.cpus[i]); + else + do_thiscpu = true; + } + + if (do_thiscpu) + cpu_request_sched (thiscpu); return r; } diff --git a/kernel/proc/mutex.c b/kernel/proc/mutex.c index 3699175..a7fa3d8 100644 --- a/kernel/proc/mutex.c +++ b/kernel/proc/mutex.c @@ -37,6 +37,8 @@ void proc_mutexes_cleanup (struct proc* proc, struct reschedule_ctx* rctx) { proc_mutex_unlock (proc, &resource->u.mutex, rctx); } + + spin_unlock (&resource->lock); } spin_unlock (&proc->procgroup->lock); diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 60ff459..0fa9fdc 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -198,10 +198,7 @@ void proc_register (struct proc* proc, struct cpu* register_cpu, struct reschedu spin_unlock (&cpu->lock); spin_unlock (&proc_tree_lock); - if (rctx != NULL) { - rctx->reschedule = true; - rctx->cpu = cpu; - } + rctx_insert_cpu (rctx, cpu); } /* caller holds cpu->lock */ @@ -225,11 +222,15 @@ static struct proc* proc_find_sched (struct cpu* cpu) { struct proc* proc = list_entry (current, struct proc, cpu_run_q_link); spin_lock (&proc->lock); - int state = proc->state; - spin_unlock (&proc->lock); - if (state == PROC_READY) + int state = proc->state; + + if (state == PROC_READY) { + spin_unlock (&proc->lock); return proc; + } + + spin_unlock (&proc->lock); current = current->next ? current->next : cpu->proc_run_q; } while (current != start); @@ -278,7 +279,7 @@ static void proc_reap (struct reschedule_ctx* rctx) { void proc_sched (void) { int s_cycles = atomic_fetch_add (&sched_cycles, 1); - struct reschedule_ctx rctx = {.reschedule = false, .cpu = NULL}; + struct reschedule_ctx rctx = {0}; if (s_cycles % SCHED_REAP_FREQ == 0) proc_reap (&rctx); @@ -321,14 +322,24 @@ void proc_kill (struct proc* proc, struct reschedule_ctx* rctx) { spin_unlock (&proc->lock); spin_unlock (&cpu->lock); - rctx->reschedule = true; - rctx->cpu = cpu; + rctx_insert_cpu (rctx, cpu); DEBUG ("killed PID %d\n", proc->pid); } +void proc_wait_for (struct proc* proc, struct reschedule_ctx* rctx, struct proc* wait_proc) { + proc_sq_suspend (proc, &wait_proc->done_sq, NULL, rctx); +} + static void proc_irq_sched (void* arg, void* regs, struct reschedule_ctx* rctx) { (void)arg, (void)regs; + +#if defined(__x86_64__) + struct saved_regs* sr = regs; + if (sr->cs != (GDT_UCODE | 0x3)) + return; +#endif + proc_sched (); } @@ -338,14 +349,14 @@ void proc_init (void) { irq_attach (&proc_irq_sched, NULL, CPU_REQUEST_SCHED); #endif - struct reschedule_ctx rctx = {.cpu = NULL, .reschedule = false}; + struct reschedule_ctx rctx = {0}; struct proc* spin_proc = proc_from_file (VFS_KERNEL, "RD", "/spin", &rctx); - proc_register (spin_proc, thiscpu, NULL); + proc_register (spin_proc, thiscpu, &rctx); struct proc* init = proc_from_file (VFS_KERNEL, "RD", "/init", &rctx); init->procgroup->capabilities |= (PROC_CAP_TERMINAL | PROC_CAP_KB); - proc_register (init, thiscpu, NULL); + proc_register (init, thiscpu, &rctx); spin_lock (&spin_proc->cpu->lock); do_sched (spin_proc, &spin_proc->cpu->lock); diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index c71a494..4b20391 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -47,6 +47,7 @@ struct proc { void* mail_recv_buffer; size_t mail_recv_size; char cwv[VOLUME_MAX]; + struct proc_suspension_q done_sq; }; void proc_sched (void); @@ -68,6 +69,8 @@ int proc_alloc_pid (void); void proc_pid_alloc_init (void); +void proc_wait_for (struct proc* proc, struct reschedule_ctx* rctx, struct proc* wait_proc); + void proc_init (void); #endif // _KERNEL_PROC_PROC_H diff --git a/kernel/proc/reschedule.h b/kernel/proc/reschedule.h index 9f9284e..3ef274d 100644 --- a/kernel/proc/reschedule.h +++ b/kernel/proc/reschedule.h @@ -6,8 +6,24 @@ #include struct reschedule_ctx { - bool reschedule; - struct cpu* cpu; + struct cpu* cpus[CPUS_MAX]; }; +#define rctx_insert_cpu(rctx, cpu) \ + do { \ + bool __found = false; \ + for (size_t __i = 0; __i < CPUS_MAX; __i++) { \ + if ((rctx)->cpus[__i] == (cpu)) \ + __found = true; \ + } \ + if (!__found) { \ + for (size_t __i = 0; __i < CPUS_MAX; __i++) { \ + if ((rctx)->cpus[__i] == NULL) { \ + (rctx)->cpus[__i] = (cpu); \ + break; \ + } \ + } \ + } \ + } while (0) + #endif // _KERNEL_PROC_RESCHEDULE_H diff --git a/kernel/proc/suspension_q.c b/kernel/proc/suspension_q.c index 43f7211..758de21 100644 --- a/kernel/proc/suspension_q.c +++ b/kernel/proc/suspension_q.c @@ -15,7 +15,8 @@ void proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock struct proc_sq_entry* sq_entry = malloc (sizeof (*sq_entry)); if (!sq_entry) { - spin_unlock (resource_lock); + if (resource_lock != NULL) + spin_unlock (resource_lock); return; } @@ -26,7 +27,8 @@ void proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock spin_lock (&proc->lock); spin_lock (&sq->lock); - spin_unlock (resource_lock); + if (resource_lock != NULL) + spin_unlock (resource_lock); proc->state = PROC_SUSPENDED; @@ -48,8 +50,7 @@ void proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock spin_unlock (&proc->lock); spin_unlock (&cpu->lock); - rctx->reschedule = true; - rctx->cpu = cpu; + rctx_insert_cpu (rctx, cpu); } void proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry, @@ -81,8 +82,7 @@ void proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry, free (sq_entry); - rctx->reschedule = true; - rctx->cpu = cpu; + rctx_insert_cpu (rctx, cpu); } void proc_sqs_cleanup (struct proc* proc) { diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index ceeff65..ff450c3 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -105,12 +105,17 @@ DEFINE_SYSCALL (sys_clone) { } /* void* argument_ptr (void) */ -DEFINE_SYSCALL (sys_argument_ptr) { return proc->uvaddr_argument; } +DEFINE_SYSCALL (sys_argument_ptr) { + spin_lock (&proc->lock); + uintptr_t p = proc->uvaddr_argument; + spin_unlock (&proc->lock); + + return p; +} /* int sched (void) */ DEFINE_SYSCALL (sys_sched) { - rctx->reschedule = true; - rctx->cpu = thiscpu; + rctx_insert_cpu (rctx, thiscpu); return SYSRESULT (ST_OK); } @@ -121,7 +126,11 @@ DEFINE_SYSCALL (sys_mutex_create) { if (mutex_resource == NULL) return SYSRESULT (-ST_OOM_ERROR); - return SYSRESULT (mutex_resource->rid); + spin_lock (&mutex_resource->lock); + int rid = mutex_resource->rid; + spin_unlock (&mutex_resource->lock); + + return SYSRESULT (rid); } /* int mutex_delete (int mutex_rid) */ @@ -425,7 +434,18 @@ DEFINE_SYSCALL (sys_get_procgroup) { if (target_proc == NULL) return SYSRESULT (-ST_NOT_FOUND); - return SYSRESULT (target_proc->procgroup->pgid); + spin_lock (&target_proc->lock); + + if (target_proc->state == PROC_DEAD) { + spin_unlock (&target_proc->lock); + return SYSRESULT (-ST_NOT_FOUND); + } + + int pgid = target_proc->procgroup->pgid; + + spin_unlock (&target_proc->lock); + + return SYSRESULT (pgid); } /* int read_dir_entry (char* path, struct dir_entry* entry, size_t entry_num) */ @@ -516,7 +536,60 @@ DEFINE_SYSCALL (sys_write_file) { } /* int get_exec_pid (void) */ -DEFINE_SYSCALL (sys_get_exec_pid) { return SYSRESULT (proc->exec_pid); } +DEFINE_SYSCALL (sys_get_exec_pid) { + spin_lock (&proc->lock); + int exec_pid = proc->exec_pid; + spin_unlock (&proc->lock); + + return SYSRESULT (exec_pid); +} + +/* wait_for_pid (int pid) */ +DEFINE_SYSCALL (sys_wait_for_pid) { + int pid = (int)a1; + + struct proc* wait_proc = proc_find_pid (pid); + + if (wait_proc == NULL) + return SYSRESULT (-ST_NOT_FOUND); + + spin_lock (&wait_proc->lock); + + if (wait_proc->state == PROC_DEAD) { + spin_unlock (&wait_proc->lock); + return SYSRESULT (-ST_NOT_FOUND); + } + + spin_unlock (&wait_proc->lock); + + proc_wait_for (proc, rctx, wait_proc); + + return SYSRESULT (ST_OK); +} + +/* int kill (int pid) */ + +DEFINE_SYSCALL (sys_kill) { + 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); + + if (target_proc->state == PROC_DEAD) { + spin_unlock (&target_proc->lock); + return SYSRESULT (-ST_NOT_FOUND); + } + + spin_unlock (&target_proc->lock); + + proc_kill (target_proc, rctx); + + return ST_OK; +} static syscall_handler_func_t handler_table[] = { [SYS_QUIT] = &sys_quit, @@ -543,6 +616,8 @@ static syscall_handler_func_t handler_table[] = { [SYS_READ_DIR_ENTRY] = &sys_read_dir_entry, [SYS_CREATE_FILE] = &sys_create_file, [SYS_WRITE_FILE] = &sys_write_file, + [SYS_WAIT_FOR_PID] = &sys_wait_for_pid, + [SYS_KILL] = &sys_kill, }; syscall_handler_func_t syscall_find_handler (int syscall_num) { diff --git a/libsystem/system.c b/libsystem/system.c index 5aaa829..2aa55c9 100644 --- a/libsystem/system.c +++ b/libsystem/system.c @@ -74,3 +74,7 @@ int create_file (const char* path) { return (int)do_syscall (SYS_CREATE_FILE, pa int write_file (const char* path, size_t off, uint8_t* buffer, size_t size) { return (int)do_syscall (SYS_WRITE_FILE, path, off, buffer, size); } + +int wait_for_pid (int pid) { return (int)do_syscall (SYS_WAIT_FOR_PID, pid); } + +int kill (int pid) { return (int)do_syscall (SYS_KILL, pid); } diff --git a/libsystem/system.h b/libsystem/system.h index abdbd59..907dfc9 100644 --- a/libsystem/system.h +++ b/libsystem/system.h @@ -87,4 +87,10 @@ int create_file (const char* path); /* write to a file */ int write_file (const char* path, size_t off, uint8_t* buffer, size_t size); +/* wait for process */ +int wait_for_pid (int pid); + +/* Kill process */ +int kill (int pid); + #endif // _LIBMSL_M_SYSTEM_H