From f103bdd7399fff8d06660d2e3ab06fb0cb8861f7 Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Wed, 18 Feb 2026 23:16:03 +0100 Subject: [PATCH] Redesign reschedule points, allow one operation to reschedule many cpus at once --- ce/ce.c | 3 +- init/init.c | 6 ++-- kernel/amd64/bootmain.c | 11 +++---- kernel/amd64/debug.c | 8 ++--- kernel/amd64/intr.c | 66 +++++++++++++++++++++++++++++++++----- kernel/amd64/proc.c | 6 ++-- kernel/amd64/sched1.c | 7 +++- kernel/amd64/smp.c | 4 +-- kernel/amd64/syscall.c | 36 +++++++++++++++++---- kernel/device/device.h | 12 +++---- kernel/device/ps2_kb.c | 19 ++++++----- kernel/device/ps2_kb.h | 9 ++++-- kernel/device/ramdrv.c | 24 +++++++------- kernel/device/ramdrv.h | 19 ++++++----- kernel/device/terminal.c | 6 ++-- kernel/device/terminal.h | 9 ++++-- kernel/fs/tarfs.c | 7 ++-- kernel/fs/tarfs.h | 4 ++- kernel/fs/vfs.c | 5 +-- kernel/fs/vfs.h | 9 ++++-- kernel/irq/irq.h | 5 +-- kernel/proc/mail.c | 44 ++++++++++++------------- kernel/proc/mail.h | 10 ++++-- kernel/proc/mutex.c | 28 +++++++--------- kernel/proc/mutex.h | 13 +++++--- kernel/proc/proc.c | 36 +++++++++------------ kernel/proc/proc.h | 14 +++++--- kernel/proc/procgroup.c | 7 ++-- kernel/proc/procgroup.h | 8 ++++- kernel/proc/reschedule.c | 32 ++++++++++++++++++ kernel/proc/reschedule.h | 20 ++++++++++++ kernel/proc/resource.c | 7 ++-- kernel/proc/resource.h | 8 +++-- kernel/proc/src.mk | 6 ++-- kernel/proc/suspension_q.c | 19 +++++------ kernel/proc/suspension_q.h | 11 ++++--- kernel/sys/proc.h | 7 +++- kernel/syscall/syscall.c | 48 +++++++++------------------ kernel/syscall/syscall.h | 6 ++-- 39 files changed, 376 insertions(+), 223 deletions(-) create mode 100644 kernel/proc/reschedule.c create mode 100644 kernel/proc/reschedule.h diff --git a/ce/ce.c b/ce/ce.c index 295c5cd..cb3be47 100644 --- a/ce/ce.c +++ b/ce/ce.c @@ -9,6 +9,7 @@ void app_main (void) { char ch; mail_receive (&ch, 1); - mail_send (e_pgid, &ch, 1); + test (ch); + /* mail_send (e_pgid, &ch, 1); */ } } diff --git a/init/init.c b/init/init.c index 6ad77fa..fd83dcc 100644 --- a/init/init.c +++ b/init/init.c @@ -18,8 +18,8 @@ void app_main (void) { mail_send (ce_pgid, (uint8_t*)&ch, 1); - char rcv; - mail_receive (&rcv, 1); - terminal_print (&rcv, 1); + /* char rcv; */ + /* mail_receive (&rcv, 1); */ + /* terminal_print (&rcv, 1); */ } } diff --git a/kernel/amd64/bootmain.c b/kernel/amd64/bootmain.c index e4fbe64..7d8d9b5 100644 --- a/kernel/amd64/bootmain.c +++ b/kernel/amd64/bootmain.c @@ -16,10 +16,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -51,14 +53,9 @@ void bootmain (void) { devices_init (); vfs_init (); - bool reschedule = false; struct device* ramdisk_device = device_find (RAMDISK_DEVICE); - struct device_op_ctx op_ctx = { - .proc = NULL, - .reschedule_cpu = NULL, - .reschedule = &reschedule, - }; - int ret = vfs_create_mountpoint ("ramdisk", VFS_TARFS, ramdisk_device, &op_ctx); + struct reschedule_ctx rctx = {.entries = NULL, .lock = SPIN_LOCK_INIT}; + int ret = vfs_create_mountpoint ("ramdisk", VFS_TARFS, ramdisk_device, NULL, &rctx); if (ret < 0) { DEBUG ("could not mount ramdisk! (%d)\n", ret); diff --git a/kernel/amd64/debug.c b/kernel/amd64/debug.c index a311973..c63130e 100644 --- a/kernel/amd64/debug.c +++ b/kernel/amd64/debug.c @@ -26,9 +26,13 @@ static bool amd64_debug_serial_tx_empty (void) { /* Write a single character to serial */ static void amd64_debug_serial_write (char x) { + spin_lock (&serial_lock); + while (!amd64_debug_serial_tx_empty ()) ; amd64_io_outb (PORT_COM1, (uint8_t)x); + + spin_unlock (&serial_lock); } /* @@ -50,14 +54,10 @@ void debugprintf (const char* fmt, ...) { const char* p = buffer; - spin_lock (&serial_lock); - while (*p) { amd64_debug_serial_write (*p); p++; } - - spin_unlock (&serial_lock); } /* Initialize serial */ diff --git a/kernel/amd64/intr.c b/kernel/amd64/intr.c index 861d6b9..30e7721 100644 --- a/kernel/amd64/intr.c +++ b/kernel/amd64/intr.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -155,9 +157,34 @@ static void amd64_intr_exception (struct saved_regs* regs) { regs->rbx); if (regs->cs == (GDT_UCODE | 0x03)) { - struct cpu* reschedule_cpu; - if (proc_kill (thiscpu->proc_current, &reschedule_cpu) == PROC_NEED_RESCHEDULE) - cpu_request_sched (reschedule_cpu); + struct reschedule_ctx rctx = {.entries = NULL, .lock = SPIN_LOCK_INIT}; + + proc_kill (thiscpu->proc_current, &rctx); + + bool reschedule_thiscpu = false; + + spin_lock (&rctx.lock); + + struct list_node_link *node, *tmp; + list_foreach (rctx.entries, node, tmp) { + struct reschedule_entry* entry = list_entry (node, struct reschedule_entry, link); + struct cpu* cpu = entry->cpu; + + if (cpu != thiscpu) { + cpu_request_sched (cpu); + } else { + reschedule_thiscpu = true; + } + + list_remove (rctx.entries, &entry->link); + free (entry); + } + + spin_unlock (&rctx.lock); + + if (reschedule_thiscpu) { + proc_sched (); + } } else { spin (); } @@ -185,12 +212,35 @@ void amd64_intr_handler (void* stack_ptr) { struct irq* irq = irq_find (regs->trap); - if (irq != NULL) { - struct cpu* reschedule_cpu = NULL; - bool reschedule = irq->func (&reschedule_cpu, irq->arg, stack_ptr); + if (irq == NULL) + return; - if (reschedule) - cpu_request_sched (reschedule_cpu); + struct reschedule_ctx rctx = {.entries = NULL, .lock = SPIN_LOCK_INIT}; + irq->func (irq->arg, stack_ptr, &rctx); + + bool reschedule_thiscpu = false; + + spin_lock (&rctx.lock); + + struct list_node_link *node, *tmp; + list_foreach (rctx.entries, node, tmp) { + struct reschedule_entry* entry = list_entry (node, struct reschedule_entry, link); + struct cpu* cpu = entry->cpu; + + if (cpu != thiscpu) { + cpu_request_sched (cpu); + } else { + reschedule_thiscpu = true; + } + + list_remove (rctx.entries, &entry->link); + free (entry); + } + + spin_unlock (&rctx.lock); + + if (reschedule_thiscpu) { + proc_sched (); } } } diff --git a/kernel/amd64/proc.c b/kernel/amd64/proc.c index 52d71e4..71405c4 100644 --- a/kernel/amd64/proc.c +++ b/kernel/amd64/proc.c @@ -99,14 +99,14 @@ struct proc* proc_clone (struct proc* proto, uintptr_t vstack_top, uintptr_t ent return proc; } -void proc_cleanup (struct proc* proc) { +void proc_cleanup (struct proc* proc, struct reschedule_ctx* rctx) { proc_sqs_cleanup (proc); - proc_mutexes_cleanup (proc); + proc_mutexes_cleanup (proc, rctx); pmm_free (proc->pdata.kernel_stack, KSTACK_SIZE / PAGE_SIZE); procgroup_unmap (proc->procgroup, proc->pdata.tls_vaddr, proc->procgroup->tls.tls_tmpl_pages); - procgroup_detach (proc->procgroup, proc); + procgroup_detach (proc->procgroup, proc, rctx); /* clean the process */ free (proc); diff --git a/kernel/amd64/sched1.c b/kernel/amd64/sched1.c index d642165..b9b8e57 100644 --- a/kernel/amd64/sched1.c +++ b/kernel/amd64/sched1.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -14,8 +15,12 @@ void do_sched (struct proc* proc, spin_lock_t* cpu_lock) { thiscpu->syscall_kernel_stack = proc->pdata.kernel_stack; amd64_wrmsr (MSR_FS_BASE, proc->pdata.fs_base); + void* cr3 = (void*)proc->procgroup->pd.cr3_paddr; + struct saved_regs regs; + memcpy (®s, &proc->pdata.regs, sizeof (regs)); + spin_unlock (&proc->lock); spin_unlock (cpu_lock); - amd64_do_sched ((void*)&proc->pdata.regs, (void*)proc->procgroup->pd.cr3_paddr); + amd64_do_sched ((void*)®s, cr3); } diff --git a/kernel/amd64/smp.c b/kernel/amd64/smp.c index 29f7f41..4b6e6c3 100644 --- a/kernel/amd64/smp.c +++ b/kernel/amd64/smp.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -88,8 +89,7 @@ static void amd64_smp_bootstrap (struct limine_mp_info* mp_info) { atomic_fetch_sub (&cpu_counter, 1); struct proc* spin_proc = proc_from_file (NULL, "ramdisk", "/spin"); - struct cpu* spin_cpu = thiscpu; - proc_register (spin_proc, &spin_cpu); + proc_register (spin_proc, thiscpu, NULL); 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 27d1517..8810b4d 100644 --- a/kernel/amd64/syscall.c +++ b/kernel/amd64/syscall.c @@ -3,10 +3,13 @@ #include #include #include +#include #include #include #include +#include #include +#include #include #include #include @@ -34,11 +37,10 @@ uintptr_t amd64_syscall_dispatch (void* stack_ptr) { return -ST_SYSCALL_NOT_FOUND; } - bool reschedule = false; + struct reschedule_ctx rctx = {.entries = NULL, .lock = SPIN_LOCK_INIT}; - struct cpu* reschedule_cpu = NULL; - uintptr_t r = func (caller, regs, &reschedule, &reschedule_cpu, regs->rdi, regs->rsi, regs->rdx, - regs->r10, regs->r8, regs->r9); + uintptr_t r = + func (caller, regs, &rctx, regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8, regs->r9); caller = proc_find_pid (caller_pid); @@ -48,8 +50,30 @@ uintptr_t amd64_syscall_dispatch (void* stack_ptr) { spin_unlock (&caller->lock); } - if (reschedule) - cpu_request_sched (reschedule_cpu); + bool reschedule_thiscpu = false; + + spin_lock (&rctx.lock); + + struct list_node_link *node, *tmp; + list_foreach (rctx.entries, node, tmp) { + struct reschedule_entry* entry = list_entry (node, struct reschedule_entry, link); + struct cpu* cpu = entry->cpu; + + if (cpu != thiscpu) { + cpu_request_sched (cpu); + } else { + reschedule_thiscpu = true; + } + + list_remove (rctx.entries, &entry->link); + free (entry); + } + + spin_unlock (&rctx.lock); + + if (reschedule_thiscpu) { + proc_sched (); + } return r; } diff --git a/kernel/device/device.h b/kernel/device/device.h index a4ab2dc..e5e5583 100644 --- a/kernel/device/device.h +++ b/kernel/device/device.h @@ -1,22 +1,18 @@ #ifndef _KERNEL_DEVICE_DEVICE_H #define _KERNEL_DEVICE_DEVICE_H +#include #include #include #include +#include #include #include struct device; -struct device_op_ctx { - struct proc* proc; - struct cpu** reschedule_cpu; - bool* reschedule; -}; - -typedef int (*device_op_func_t) (struct device* device, struct device_op_ctx* op_ctx, void* a1, - void* a2, void* a3, void* a4); +typedef int (*device_op_func_t) (struct device* device, struct proc*, struct reschedule_ctx* rctx, + void* a1, void* a2, void* a3, void* a4); typedef bool (*device_init_func_t) (struct device* device, void* arg); typedef void (*device_fini_func_t) (struct device* device); diff --git a/kernel/device/ps2_kb.c b/kernel/device/ps2_kb.c index 70b7c99..be433f9 100644 --- a/kernel/device/ps2_kb.c +++ b/kernel/device/ps2_kb.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -165,13 +166,13 @@ static int32_t ps2kb_keycode (void) { return c; } -static bool ps2kb_irq (struct cpu** reschedule_cpu, void* arg, void* regs) { +static void ps2kb_irq (void* arg, void* regs, struct reschedule_ctx* rctx) { (void)arg, (void)regs; int32_t keycode = ps2kb_keycode (); if (keycode <= 0) - return PROC_NO_RESCHEDULE; + return; spin_lock (&ps2kb_ringbuffer_lock); spin_lock (&ps2kb_sq.lock); @@ -187,20 +188,19 @@ static bool ps2kb_irq (struct cpu** reschedule_cpu, void* arg, void* regs) { spin_unlock (&ps2kb_sq.lock); spin_unlock (&ps2kb_ringbuffer_lock); - return proc_sq_resume (resumed_proc, sq_entry, reschedule_cpu); + proc_sq_resume (resumed_proc, sq_entry, rctx); + return; } spin_unlock (&ps2kb_sq.lock); spin_unlock (&ps2kb_ringbuffer_lock); - - return PROC_NO_RESCHEDULE; } -int ps2kb_read_key (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4) { +int ps2kb_read_key (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, void* a1, + void* a2, void* a3, void* a4) { (void)device, (void)a2, (void)a3, (void)a4; - if ((op_ctx->proc != NULL) && !(op_ctx->proc->procgroup->capabilities & PROC_CAP_KB)) + if (!(proc->procgroup->capabilities & PROC_CAP_KB)) return -ST_PERMISSION_ERROR; uint8_t* chbuf = (uint8_t*)a1; @@ -224,8 +224,7 @@ int ps2kb_read_key (struct device* device, struct device_op_ctx* op_ctx, void* a return -ST_PERMISSION_ERROR; } - *op_ctx->reschedule = - proc_sq_suspend (op_ctx->proc, &ps2kb_sq, &ps2kb_ringbuffer_lock, op_ctx->reschedule_cpu); + proc_sq_suspend (proc, &ps2kb_sq, &ps2kb_ringbuffer_lock, rctx); return ST_OK; } diff --git a/kernel/device/ps2_kb.h b/kernel/device/ps2_kb.h index 97397c8..13aed72 100644 --- a/kernel/device/ps2_kb.h +++ b/kernel/device/ps2_kb.h @@ -1,14 +1,19 @@ #ifndef _KERNEL_DEVICE_PS2_KB_H #define _KERNEL_DEVICE_PS2_KB_H +#include #include +#include +#include struct device; struct device_op_ctx; -int ps2kb_read_key (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4); +int ps2kb_read_key (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, void* a1, + void* a2, void* a3, void* a4); + bool ps2kb_init (struct device* device, void* arg); + void ps2kb_fini (struct device* device); #endif // _KERNEL_DEVICE_PS2_KB_H diff --git a/kernel/device/ramdrv.c b/kernel/device/ramdrv.c index 6378de7..6b9fd9c 100644 --- a/kernel/device/ramdrv.c +++ b/kernel/device/ramdrv.c @@ -43,9 +43,9 @@ void ramdrv_fini (struct device* device) { free (ramdrv); } -int ramdrv_get_device_type (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4) { - (void)device, (void)a2, (void)a3, (void)a4, (void)op_ctx; +int ramdrv_get_device_type (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, + void* a1, void* a2, void* a3, void* a4) { + (void)device, (void)a2, (void)a3, (void)a4; if (a1 == NULL) return -ST_BAD_ADDRESS_SPACE; @@ -57,9 +57,9 @@ int ramdrv_get_device_type (struct device* device, struct device_op_ctx* op_ctx, return ST_OK; } -int ramdrv_get_size (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4) { - (void)a2, (void)a3, (void)a4, (void)op_ctx; +int ramdrv_get_size (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, + void* a1, void* a2, void* a3, void* a4) { + (void)a2, (void)a3, (void)a4; if (a1 == NULL) return -ST_BAD_ADDRESS_SPACE; @@ -73,9 +73,9 @@ int ramdrv_get_size (struct device* device, struct device_op_ctx* op_ctx, void* return ST_OK; } -int ramdrv_get_sector_size (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4) { - (void)a2, (void)a3, (void)a4, (void)op_ctx; +int ramdrv_get_sector_size (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, + void* a1, void* a2, void* a3, void* a4) { + (void)a2, (void)a3, (void)a4; if (a1 == NULL) return -ST_BAD_ADDRESS_SPACE; @@ -89,9 +89,9 @@ int ramdrv_get_sector_size (struct device* device, struct device_op_ctx* op_ctx, return ST_OK; } -int ramdrv_read (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, void* a3, - void* a4) { - (void)op_ctx, (void)a4; +int ramdrv_read (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, void* a1, + void* a2, void* a3, void* a4) { + (void)a4; if (a1 == NULL || a2 == NULL || a3 == NULL) return -ST_BAD_ADDRESS_SPACE; diff --git a/kernel/device/ramdrv.h b/kernel/device/ramdrv.h index 8bbf692..b2063ab 100644 --- a/kernel/device/ramdrv.h +++ b/kernel/device/ramdrv.h @@ -1,7 +1,10 @@ #ifndef _KERNEL_DEVICE_RAMDRV_H #define _KERNEL_DEVICE_RAMDRV_H +#include #include +#include +#include struct device; struct device_op_ctx; @@ -23,16 +26,16 @@ bool ramdrv_init (struct device* device, void* arg); void ramdrv_fini (struct device* device); -int ramdrv_read (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, void* a3, - void* a4); +int ramdrv_read (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, void* a1, + void* a2, void* a3, void* a4); -int ramdrv_get_device_type (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4); +int ramdrv_get_device_type (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, + void* a1, void* a2, void* a3, void* a4); -int ramdrv_get_sector_size (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4); +int ramdrv_get_sector_size (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, + void* a1, void* a2, void* a3, void* a4); -int ramdrv_get_size (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4); +int ramdrv_get_size (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, + void* a1, void* a2, void* a3, void* a4); #endif // _KERNEL_DEVICE_RAMDRV_H diff --git a/kernel/device/terminal.c b/kernel/device/terminal.c index 1855b07..f0ab74a 100644 --- a/kernel/device/terminal.c +++ b/kernel/device/terminal.c @@ -35,11 +35,11 @@ bool terminal_init (struct device* device, void* arg) { void terminal_fini (struct device* device) { (void)device; } -int terminal_putstr (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4) { +int terminal_putstr (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, + void* a1, void* a2, void* a3, void* a4) { (void)a2, (void)a3, (void)a4, (void)device; - if ((op_ctx->proc != NULL) && !(op_ctx->proc->procgroup->capabilities & PROC_CAP_TERMINAL)) + if (!(proc->procgroup->capabilities & PROC_CAP_TERMINAL)) return -ST_PERMISSION_ERROR; char* string = (char*)a1; diff --git a/kernel/device/terminal.h b/kernel/device/terminal.h index b756e00..571435e 100644 --- a/kernel/device/terminal.h +++ b/kernel/device/terminal.h @@ -1,14 +1,19 @@ #ifndef _KERNEL_DEVICE_TERMINAL_H #define _KERNEL_DEVICE_TERMINAL_H +#include #include +#include +#include struct device; struct device_op_ctx; bool terminal_init (struct device* device, void* arg); + void terminal_fini (struct device* device); -int terminal_putstr (struct device* device, struct device_op_ctx* op_ctx, void* a1, void* a2, - void* a3, void* a4); + +int terminal_putstr (struct device* device, struct proc* proc, struct reschedule_ctx* rctx, + void* a1, void* a2, void* a3, void* a4); #endif // _KERNEL_DEVICE_TERMINAL_H diff --git a/kernel/fs/tarfs.c b/kernel/fs/tarfs.c index 6a52ec8..2ac0bea 100644 --- a/kernel/fs/tarfs.c +++ b/kernel/fs/tarfs.c @@ -54,7 +54,8 @@ static size_t tar_parse (struct tarfs* tarfs, uint8_t* addr) { return i; } -int tarfs_mount (struct vfs_mountpoint* mountpoint, struct device_op_ctx* op_ctx) { +int tarfs_mount (struct vfs_mountpoint* mountpoint, struct proc* proc, + struct reschedule_ctx* rctx) { struct tarfs* tarfs = malloc (sizeof (*tarfs)); if (tarfs == NULL) @@ -70,7 +71,7 @@ int tarfs_mount (struct vfs_mountpoint* mountpoint, struct device_op_ctx* op_ctx spin_lock (&back_device->lock); - ret = back_device->ops[XDRV_GET_SIZE](back_device, op_ctx, &total_size, NULL, NULL, NULL); + ret = back_device->ops[XDRV_GET_SIZE](back_device, proc, rctx, &total_size, NULL, NULL, NULL); if (ret < 0) { spin_unlock (&back_device->lock); free (mountpoint->udata); @@ -86,7 +87,7 @@ int tarfs_mount (struct vfs_mountpoint* mountpoint, struct device_op_ctx* op_ctx } size_t pos = 0; - ret = back_device->ops[XDRV_READ](back_device, op_ctx, &pos, &total_size, buffer, NULL); + ret = back_device->ops[XDRV_READ](back_device, proc, rctx, &pos, &total_size, buffer, NULL); spin_unlock (&back_device->lock); diff --git a/kernel/fs/tarfs.h b/kernel/fs/tarfs.h index bf66e86..5498ae0 100644 --- a/kernel/fs/tarfs.h +++ b/kernel/fs/tarfs.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include struct tar_header { char filename[100]; @@ -31,7 +33,7 @@ struct tarfs { struct vfs_mountpoint; -int tarfs_mount (struct vfs_mountpoint* mountpoint, struct device_op_ctx* op_ctx); +int tarfs_mount (struct vfs_mountpoint* mountpoint, struct proc* proc, struct reschedule_ctx* rctx); int tarfs_describe (struct vfs_mountpoint* mountpoint, const char* path, struct fs_desc_buffer* desc); diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 14d73a1..1653964 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,7 @@ static struct vfs_mountpoint* vfs_find_mountpoint (const char* mountpoint) { } int vfs_create_mountpoint (const char* key, int fs_type, struct device* back_device, - struct device_op_ctx* op_ctx) { + struct proc* proc, struct reschedule_ctx* rctx) { if (strlen_null (key) > fieldsizeof (struct vfs_mountpoint, key)) return -ST_OOB_ERROR; @@ -60,7 +61,7 @@ int vfs_create_mountpoint (const char* key, int fs_type, struct device* back_dev } break; } - int ret = mountpoint->driver_ops.mount (mountpoint, op_ctx); + int ret = mountpoint->driver_ops.mount (mountpoint, proc, rctx); if (ret < 0) { free (mountpoint); diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index ae49a39..1af9dd4 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include #include #define VFS_TARFS 0 @@ -19,9 +21,12 @@ struct vfs_mountpoint { bool locked; struct procgroup* ownerpg; struct { - int (*mount) (struct vfs_mountpoint* mountpoint, struct device_op_ctx* op_ctx); + int (*mount) (struct vfs_mountpoint* mountpoint, struct proc* proc, + struct reschedule_ctx* rctx); + int (*describe) (struct vfs_mountpoint* mountpoint, const char* path, struct fs_desc_buffer* desc); + int (*read) (struct vfs_mountpoint* mountpoint, const char* path, uint8_t* buffer, size_t off, size_t size); } driver_ops; @@ -35,7 +40,7 @@ struct vfs_mount_table { }; int vfs_create_mountpoint (const char* key, int fs_type, struct device* back_device, - struct device_op_ctx* op_ctx); + struct proc* proc, struct reschedule_ctx* rctx); int vfs_describe (struct procgroup* procgroup, const char* mountpoint, const char* path, struct fs_desc_buffer* desc); diff --git a/kernel/irq/irq.h b/kernel/irq/irq.h index 4759b6e..c356deb 100644 --- a/kernel/irq/irq.h +++ b/kernel/irq/irq.h @@ -1,11 +1,12 @@ #ifndef _KERNEL_IRQ_IRQ_H #define _KERNEL_IRQ_IRQ_H +#include #include #include -#include +#include -typedef bool (*irq_func_t) (struct cpu** reschedule_cpu, void* arg, void* regs); +typedef void (*irq_func_t) (void* arg, void* regs, struct reschedule_ctx* rctx); struct irq { uint32_t irq_num; diff --git a/kernel/proc/mail.c b/kernel/proc/mail.c index 31d0991..22687fc 100644 --- a/kernel/proc/mail.c +++ b/kernel/proc/mail.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -8,9 +10,8 @@ #include #include -bool proc_cleanup_resource_mail (struct proc_resource* resource, struct cpu** reschedule_cpu) { +void proc_cleanup_resource_mail (struct proc_resource* resource, struct reschedule_ctx* rctx) { struct proc_mail* mail = &resource->u.mail; - bool reschedule = PROC_NO_RESCHEDULE; spin_lock (&mail->resource->lock); @@ -29,7 +30,7 @@ bool proc_cleanup_resource_mail (struct proc_resource* resource, struct cpu** re spin_unlock (&mail->send_sq.lock); spin_unlock (&mail->resource->lock); - reschedule = reschedule || proc_sq_resume (suspended_proc, sq_entry, reschedule_cpu); + proc_sq_resume (suspended_proc, sq_entry, rctx); spin_lock (&mail->resource->lock); spin_lock (&mail->send_sq.lock); @@ -38,13 +39,18 @@ bool proc_cleanup_resource_mail (struct proc_resource* resource, struct cpu** re spin_unlock (&mail->send_sq.lock); spin_unlock (&mail->resource->lock); - - return reschedule; } -bool proc_mail_send (struct proc* proc, struct proc_mail* mail, struct cpu** reschedule_cpu, +void proc_mail_send (struct proc* proc, struct proc_mail* mail, struct reschedule_ctx* rctx, void* data, size_t data_size) { spin_lock (&mail->resource->lock); + + /* mail full */ + if (mail->pending_mesg != NULL) { + proc_sq_suspend (proc, &mail->send_sq, &mail->resource->lock, rctx); + return; + } + spin_lock (&mail->recv_sq.lock); /* if receiver available, hand off directly */ @@ -57,40 +63,33 @@ bool proc_mail_send (struct proc* proc, struct proc_mail* mail, struct cpu** res spin_unlock (&mail->recv_sq.lock); spin_unlock (&mail->resource->lock); - spin_lock (&proc->lock); + spin_lock (&resumed_proc->lock); if (resumed_proc->mail_recv_buffer != NULL) { - size_t copy_size = - (data_size < resumed_proc->mail_recv_size) ? data_size : resumed_proc->mail_recv_size; + size_t copy_size = min (data_size, resumed_proc->mail_recv_size); memcpy (resumed_proc->mail_recv_buffer, data, copy_size); resumed_proc->mail_recv_buffer = NULL; resumed_proc->mail_recv_size = 0; } - spin_unlock (&proc->lock); + spin_unlock (&resumed_proc->lock); - return proc_sq_resume (resumed_proc, sq_entry, reschedule_cpu); + proc_sq_resume (resumed_proc, sq_entry, rctx); + return; } spin_unlock (&mail->recv_sq.lock); - /* mail full */ - if (mail->pending_mesg != NULL) { - return proc_sq_suspend (proc, &mail->send_sq, &mail->resource->lock, reschedule_cpu); - } - /* mail is empty and nobody is waiting */ mail->pending_mesg = malloc (data_size); memcpy (mail->pending_mesg, data, data_size); mail->pending_mesg_size = data_size; spin_unlock (&mail->resource->lock); - - return PROC_NO_RESCHEDULE; } -bool proc_mail_receive (struct proc* proc, struct proc_mail* mail, struct cpu** reschedule_cpu, +void proc_mail_receive (struct proc* proc, struct proc_mail* mail, struct reschedule_ctx* rctx, void* recv_buffer, size_t recv_size) { spin_lock (&proc->lock); proc->mail_recv_buffer = recv_buffer; @@ -118,15 +117,16 @@ bool proc_mail_receive (struct proc* proc, struct proc_mail* mail, struct cpu** spin_unlock (&mail->send_sq.lock); spin_unlock (&mail->resource->lock); - return proc_sq_resume (resumed_proc, sq_entry, reschedule_cpu); + proc_sq_resume (resumed_proc, sq_entry, rctx); + return; } spin_unlock (&mail->send_sq.lock); spin_unlock (&mail->resource->lock); - return PROC_NO_RESCHEDULE; + return; } /* nothing to receive */ - return proc_sq_suspend (proc, &mail->recv_sq, &mail->resource->lock, reschedule_cpu); + proc_sq_suspend (proc, &mail->recv_sq, &mail->resource->lock, rctx); } diff --git a/kernel/proc/mail.h b/kernel/proc/mail.h index d58c401..29cc9f7 100644 --- a/kernel/proc/mail.h +++ b/kernel/proc/mail.h @@ -1,12 +1,14 @@ #ifndef _KERNEL_PROC_MAIL_H #define _KERNEL_PROC_MAIL_H +#include #include #include struct proc; struct proc_resource; struct cpu; +struct reschedule_ctx; struct proc_mail { struct proc_resource* resource; @@ -17,10 +19,12 @@ struct proc_mail { size_t pending_mesg_size; }; -bool proc_cleanup_resource_mail (struct proc_resource* resource, struct cpu** reschedule_cpu); -bool proc_mail_send (struct proc* proc, struct proc_mail* mail, struct cpu** reschedule_cpu, +void proc_cleanup_resource_mail (struct proc_resource* resource, struct reschedule_ctx* rctx); + +void proc_mail_send (struct proc* proc, struct proc_mail* mail, struct reschedule_ctx* rctx, void* data, size_t data_size); -bool proc_mail_receive (struct proc* proc, struct proc_mail* mail, struct cpu** reschedule_cpu, + +void proc_mail_receive (struct proc* proc, struct proc_mail* mail, struct reschedule_ctx* rctx, void* recv_buffer, size_t recv_size); #endif // _KERNEL_PROC_MAIL_H diff --git a/kernel/proc/mutex.c b/kernel/proc/mutex.c index e2abf30..3699175 100644 --- a/kernel/proc/mutex.c +++ b/kernel/proc/mutex.c @@ -11,7 +11,7 @@ #include #include -void proc_mutexes_cleanup (struct proc* proc) { +void proc_mutexes_cleanup (struct proc* proc, struct reschedule_ctx* rctx) { spin_lock (&proc->procgroup->lock); struct rb_node_link* rnode; @@ -35,22 +35,19 @@ void proc_mutexes_cleanup (struct proc* proc) { if (resource->u.mutex.owner == proc && resource->u.mutex.locked) { spin_unlock (&resource->lock); - struct cpu* reschedule_cpu; - proc_mutex_unlock (proc, &resource->u.mutex, &reschedule_cpu); + proc_mutex_unlock (proc, &resource->u.mutex, rctx); } } spin_unlock (&proc->procgroup->lock); } -bool proc_cleanup_resource_mutex (struct proc_resource* resource, struct cpu** reschedule_cpu) { +void proc_cleanup_resource_mutex (struct proc_resource* resource, struct reschedule_ctx* rctx) { struct proc_mutex* mutex = &resource->u.mutex; spin_lock (&mutex->resource->lock); spin_lock (&mutex->suspension_q.lock); - bool reschedule = PROC_NO_RESCHEDULE; - while (mutex->suspension_q.proc_list != NULL) { struct list_node_link* node = mutex->suspension_q.proc_list; struct proc_sq_entry* sq_entry = list_entry (node, struct proc_sq_entry, sq_link); @@ -60,7 +57,7 @@ bool proc_cleanup_resource_mutex (struct proc_resource* resource, struct cpu** r spin_unlock (&mutex->suspension_q.lock); spin_unlock (&mutex->resource->lock); - reschedule = reschedule || proc_sq_resume (suspended_proc, sq_entry, reschedule_cpu); + proc_sq_resume (suspended_proc, sq_entry, rctx); /* reacquire */ spin_lock (&mutex->resource->lock); @@ -72,29 +69,27 @@ bool proc_cleanup_resource_mutex (struct proc_resource* resource, struct cpu** r spin_unlock (&mutex->suspension_q.lock); spin_unlock (&mutex->resource->lock); - - return reschedule; } -bool proc_mutex_lock (struct proc* proc, struct proc_mutex* mutex, struct cpu** reschedule_cpu) { +void proc_mutex_lock (struct proc* proc, struct proc_mutex* mutex, struct reschedule_ctx* rctx) { spin_lock (&mutex->resource->lock); if (!mutex->locked || mutex->owner == proc) { mutex->locked = true; mutex->owner = proc; spin_unlock (&mutex->resource->lock); - return PROC_NO_RESCHEDULE; + return; } - return proc_sq_suspend (proc, &mutex->suspension_q, &mutex->resource->lock, reschedule_cpu); + proc_sq_suspend (proc, &mutex->suspension_q, &mutex->resource->lock, rctx); } -bool proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex, struct cpu** reschedule_cpu) { +void proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex, struct reschedule_ctx* rctx) { spin_lock (&mutex->resource->lock); if (mutex->owner != proc) { spin_unlock (&mutex->resource->lock); - return PROC_NO_RESCHEDULE; + return; } spin_lock (&mutex->suspension_q.lock); @@ -111,7 +106,8 @@ bool proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex, struct cpu* spin_unlock (&mutex->suspension_q.lock); spin_unlock (&mutex->resource->lock); - return proc_sq_resume (resumed_proc, sq_entry, reschedule_cpu); + proc_sq_resume (resumed_proc, sq_entry, rctx); + return; } mutex->locked = false; @@ -119,6 +115,4 @@ bool proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex, struct cpu* spin_unlock (&mutex->suspension_q.lock); spin_unlock (&mutex->resource->lock); - - return PROC_NO_RESCHEDULE; } diff --git a/kernel/proc/mutex.h b/kernel/proc/mutex.h index 1abe882..bc071c4 100644 --- a/kernel/proc/mutex.h +++ b/kernel/proc/mutex.h @@ -1,12 +1,14 @@ #ifndef _KERNEL_PROC_MUTEX_H #define _KERNEL_PROC_MUTEX_H +#include #include #include struct proc; struct proc_resource; struct cpu; +struct reschedule_ctx; struct proc_mutex { struct proc_resource* resource; @@ -16,9 +18,12 @@ struct proc_mutex { struct proc* owner; }; -bool proc_cleanup_resource_mutex (struct proc_resource* resource, struct cpu** reschedule_cpu); -bool proc_mutex_lock (struct proc* proc, struct proc_mutex* mutex, struct cpu** reschedule_cpu); -bool proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex, struct cpu** reschedule_cpu); -void proc_mutexes_cleanup (struct proc* proc); +void proc_cleanup_resource_mutex (struct proc_resource* resource, struct reschedule_ctx* rctx); + +void proc_mutex_lock (struct proc* proc, struct proc_mutex* mutex, struct reschedule_ctx* rctx); + +void proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex, struct reschedule_ctx* rctx); + +void proc_mutexes_cleanup (struct proc* proc, struct reschedule_ctx* rctx); #endif // _KERNEL_PROC_MUTEX_H diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index f98e508..5a7a9d1 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -160,8 +161,8 @@ struct proc* proc_find_pid (int pid) { return proc; } -bool proc_register (struct proc* proc, struct cpu** reschedule_cpu) { - struct cpu* cpu = *reschedule_cpu != NULL ? *reschedule_cpu : cpu_find_lightest (); +void proc_register (struct proc* proc, struct cpu* register_cpu, struct reschedule_ctx* rctx) { + struct cpu* cpu = register_cpu != NULL ? register_cpu : cpu_find_lightest (); spin_lock (&proc_tree_lock); spin_lock (&cpu->lock); @@ -180,9 +181,8 @@ bool proc_register (struct proc* proc, struct cpu** reschedule_cpu) { spin_unlock (&cpu->lock); spin_unlock (&proc_tree_lock); - *reschedule_cpu = cpu; - - return PROC_NEED_RESCHEDULE; + if (rctx != NULL) + reschedule_list_append (rctx, cpu); } /* caller holds cpu->lock */ @@ -214,7 +214,7 @@ static struct proc* proc_find_sched (struct cpu* cpu) { return NULL; } -static void proc_reap (void) { +static void proc_reap (struct reschedule_ctx* rctx) { struct proc* proc = NULL; struct list_node_link* reap_list = NULL; @@ -246,15 +246,16 @@ static void proc_reap (void) { list_remove (reap_list, &proc->reap_link); DEBUG ("cleanup PID %d\n", proc->pid); - proc_cleanup (proc); + proc_cleanup (proc, rctx); } } void proc_sched (void) { int s_cycles = atomic_fetch_add (&sched_cycles, 1); + struct reschedule_ctx rctx = {.entries = NULL, .lock = SPIN_LOCK_INIT}; if (s_cycles % SCHED_REAP_FREQ == 0) - proc_reap (); + proc_reap (&rctx); struct proc* next = NULL; struct cpu* cpu = thiscpu; @@ -275,7 +276,7 @@ void proc_sched (void) { } } -bool proc_kill (struct proc* proc, struct cpu** reschedule_cpu) { +void proc_kill (struct proc* proc, struct reschedule_ctx* rctx) { spin_lock (&proc->lock); struct cpu* cpu = proc->cpu; spin_unlock (&proc->lock); @@ -294,17 +295,14 @@ bool proc_kill (struct proc* proc, struct cpu** reschedule_cpu) { spin_unlock (&proc->lock); spin_unlock (&cpu->lock); + reschedule_list_append (rctx, cpu); + DEBUG ("killed PID %d\n", proc->pid); - - *reschedule_cpu = cpu; - - return PROC_NEED_RESCHEDULE; } -static bool proc_irq_sched (struct cpu** reschedule_cpu, void* arg, void* regs) { - (void)arg, (void)regs, (void)reschedule_cpu; +static void proc_irq_sched (void* arg, void* regs, struct reschedule_ctx* rctx) { + (void)arg, (void)regs; proc_sched (); - return PROC_NO_RESCHEDULE; } void proc_init (void) { @@ -314,13 +312,11 @@ void proc_init (void) { #endif struct proc* spin_proc = proc_from_file (NULL, "ramdisk", "/spin"); - struct cpu* spin_cpu = thiscpu; - proc_register (spin_proc, &spin_cpu); + proc_register (spin_proc, thiscpu, NULL); struct proc* init = proc_from_file (NULL, "ramdisk", "/init"); init->procgroup->capabilities |= (PROC_CAP_TERMINAL | PROC_CAP_KB); - struct cpu* init_cpu = thiscpu; - proc_register (init, &init_cpu); + proc_register (init, thiscpu, NULL); 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 054fb1d..3584596 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -17,9 +17,6 @@ #include /* USTACK_SIZE */ #endif -#define PROC_NEED_RESCHEDULE true -#define PROC_NO_RESCHEDULE false - /* process states */ #define PROC_READY 0 #define PROC_DEAD 1 @@ -29,6 +26,7 @@ #define PROC_USTK_PREALLOC (1 << 0) struct cpu; +struct reschedule_ctx; struct proc { int pid; @@ -50,11 +48,17 @@ struct proc { }; void proc_sched (void); -bool proc_kill (struct proc* proc, struct cpu** reschedule_cpu); + +void proc_kill (struct proc* proc, struct reschedule_ctx* rctx); + struct elf_aux proc_load_segments (struct proc* proc, uint8_t* elf); -bool proc_register (struct proc* proc, struct cpu** reschedule_cpu); + +void proc_register (struct proc* proc, struct cpu* register_cpu, struct reschedule_ctx* rctx); + struct proc* proc_find_pid (int pid); + struct proc* proc_from_file (struct procgroup* procgroup, const char* mountpoint, const char* path); + void proc_init (void); #endif // _KERNEL_PROC_PROC_H diff --git a/kernel/proc/procgroup.c b/kernel/proc/procgroup.c index b2dd17f..4bc9dbc 100644 --- a/kernel/proc/procgroup.c +++ b/kernel/proc/procgroup.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -176,7 +177,8 @@ void procgroup_attach (struct procgroup* procgroup, struct proc* proc) { spin_unlock (&procgroup->lock); } -void procgroup_detach (struct procgroup* procgroup, struct proc* proc) { +void procgroup_detach (struct procgroup* procgroup, struct proc* proc, + struct reschedule_ctx* rctx) { spin_lock (&procgroup->lock); spin_lock (&proc->lock); @@ -207,8 +209,7 @@ void procgroup_detach (struct procgroup* procgroup, struct proc* proc) { rnode = next; - struct cpu* reschedule_cpu; - proc_delete_resource (resource, &reschedule_cpu); + proc_delete_resource (resource, rctx); } /* unlock VFS owned mountpoints */ diff --git a/kernel/proc/procgroup.h b/kernel/proc/procgroup.h index 270ed45..a83e28f 100644 --- a/kernel/proc/procgroup.h +++ b/kernel/proc/procgroup.h @@ -10,6 +10,7 @@ #include struct proc; +struct reschedule_ctx; struct proc_mapping { struct list_node_link proc_mappings_link; @@ -35,11 +36,16 @@ struct procgroup { }; struct procgroup* procgroup_create (void); + void procgroup_attach (struct procgroup* procgroup, struct proc* proc); -void procgroup_detach (struct procgroup* procgroup, struct proc* proc); + +void procgroup_detach (struct procgroup* procgroup, struct proc* proc, struct reschedule_ctx* rctx); + uintptr_t procgroup_map (struct procgroup* procgroup, uintptr_t vaddr, size_t pages, uint32_t flags, uintptr_t* out_paddr); + bool procgroup_unmap (struct procgroup* procgroup, uintptr_t start_vaddr, size_t pages); + struct procgroup* procgroup_find (int pgid); #endif // _KERNEL_PROC_PROCGROUP_H diff --git a/kernel/proc/reschedule.c b/kernel/proc/reschedule.c new file mode 100644 index 0000000..1821093 --- /dev/null +++ b/kernel/proc/reschedule.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include + +void reschedule_list_append (struct reschedule_ctx* rctx, struct cpu* cpu) { + spin_lock (&rctx->lock); + + struct list_node_link *node, *tmp; + list_foreach (rctx->entries, node, tmp) { + struct reschedule_entry* entry = list_entry (node, struct reschedule_entry, link); + + if (entry->cpu == cpu) { + spin_unlock (&rctx->lock); + return; + } + } + + struct reschedule_entry* entry = malloc (sizeof (*entry)); + + if (entry == NULL) { + spin_unlock (&rctx->lock); + return; + } + + entry->cpu = cpu; + + list_append (rctx->entries, &entry->link); + + spin_unlock (&rctx->lock); +} diff --git a/kernel/proc/reschedule.h b/kernel/proc/reschedule.h new file mode 100644 index 0000000..ad9c8c1 --- /dev/null +++ b/kernel/proc/reschedule.h @@ -0,0 +1,20 @@ +#ifndef _KERNEL_PROC_RESCHEDULE_H +#define _KERNEL_PROC_RESCHEDULE_H + +#include +#include +#include + +struct reschedule_entry { + struct cpu* cpu; + struct list_node_link link; +}; + +struct reschedule_ctx { + struct list_node_link* entries; + spin_lock_t lock; +}; + +void reschedule_list_append (struct reschedule_ctx* rctx, struct cpu* cpu); + +#endif // _KERNEL_PROC_RESCHEDULE_H diff --git a/kernel/proc/resource.c b/kernel/proc/resource.c index 95b5804..a7c9bdf 100644 --- a/kernel/proc/resource.c +++ b/kernel/proc/resource.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -76,9 +77,7 @@ struct proc_resource* proc_create_resource_mail (struct procgroup* procgroup, in return resource; } -bool proc_delete_resource (struct proc_resource* resource, struct cpu** reschedule_cpu) { - bool reschedule = resource->ops.cleanup (resource, reschedule_cpu); +void proc_delete_resource (struct proc_resource* resource, struct reschedule_ctx* rctx) { + resource->ops.cleanup (resource, rctx); free (resource); - - return reschedule; } diff --git a/kernel/proc/resource.h b/kernel/proc/resource.h index d3a61d6..9e982bb 100644 --- a/kernel/proc/resource.h +++ b/kernel/proc/resource.h @@ -14,6 +14,7 @@ struct proc; struct procgroup; struct cpu; +struct reschedule_ctx; struct proc_resource { int type; @@ -25,13 +26,16 @@ struct proc_resource { struct proc_mail mail; } u; struct { - bool (*cleanup) (struct proc_resource* resource, struct cpu** reschedule_cpu); + void (*cleanup) (struct proc_resource* resource, struct reschedule_ctx* rctx); } ops; }; struct proc_resource* proc_find_resource (struct procgroup* procgroup, int rid); + struct proc_resource* proc_create_resource_mutex (struct procgroup* procgroup, int rid); + struct proc_resource* proc_create_resource_mail (struct procgroup* procgroup, int rid); -bool proc_delete_resource (struct proc_resource* resource, struct cpu** reschedule_cpu); + +void proc_delete_resource (struct proc_resource* resource, struct reschedule_ctx* rctx); #endif // _KERNEL_PROC_RESOURCE_H diff --git a/kernel/proc/src.mk b/kernel/proc/src.mk index 5b1510f..538ba53 100644 --- a/kernel/proc/src.mk +++ b/kernel/proc/src.mk @@ -3,11 +3,13 @@ c += proc/proc.c \ proc/mutex.c \ proc/procgroup.c \ proc/suspension_q.c \ - proc/mail.c + proc/mail.c \ + proc/reschedule.c o += proc/proc.o \ proc/resource.o \ proc/mutex.o \ proc/procgroup.o \ proc/suspension_q.o \ - proc/mail.o + proc/mail.o \ + proc/reschedule.o diff --git a/kernel/proc/suspension_q.c b/kernel/proc/suspension_q.c index c209e5c..72d0c1f 100644 --- a/kernel/proc/suspension_q.c +++ b/kernel/proc/suspension_q.c @@ -2,20 +2,21 @@ #include #include #include +#include #include #include #include #include #include -bool proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock_t* resource_lock, - struct cpu** reschedule_cpu) { +void proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock_t* resource_lock, + struct reschedule_ctx* rctx) { struct cpu* cpu = proc->cpu; struct proc_sq_entry* sq_entry = malloc (sizeof (*sq_entry)); if (!sq_entry) { spin_unlock (resource_lock); - return PROC_NO_RESCHEDULE; + return; } sq_entry->proc = proc; @@ -47,13 +48,11 @@ bool proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock spin_unlock (&proc->lock); spin_unlock (&cpu->lock); - *reschedule_cpu = cpu; - - return PROC_NEED_RESCHEDULE; + reschedule_list_append (rctx, cpu); } -bool proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry, - struct cpu** reschedule_cpu) { +void proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry, + struct reschedule_ctx* rctx) { struct cpu* cpu = cpu_find_lightest (); struct proc_suspension_q* sq = sq_entry->sq; @@ -81,9 +80,7 @@ bool proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry, free (sq_entry); - *reschedule_cpu = cpu; - - return PROC_NEED_RESCHEDULE; + reschedule_list_append (rctx, cpu); } void proc_sqs_cleanup (struct proc* proc) { diff --git a/kernel/proc/suspension_q.h b/kernel/proc/suspension_q.h index 321b054..3a29e67 100644 --- a/kernel/proc/suspension_q.h +++ b/kernel/proc/suspension_q.h @@ -6,6 +6,7 @@ struct proc; struct cpu; +struct reschedule_ctx; struct proc_suspension_q { struct list_node_link* proc_list; @@ -20,9 +21,11 @@ struct proc_sq_entry { }; void proc_sqs_cleanup (struct proc* proc); -bool proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock_t* resource_lock, - struct cpu** reschedule_cpu); -bool proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry, - struct cpu** reschedule_cpu); + +void proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock_t* resource_lock, + struct reschedule_ctx* rctx); + +void proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry, + struct reschedule_ctx* rctx); #endif // _KERNEL_PROC_SUSPENTION_Q_H diff --git a/kernel/sys/proc.h b/kernel/sys/proc.h index 9269ec6..6d1d82f 100644 --- a/kernel/sys/proc.h +++ b/kernel/sys/proc.h @@ -1,14 +1,19 @@ #ifndef _KERNEL_SYS_PROC_H #define _KERNEL_SYS_PROC_H +#include #include +#include struct proc; struct proc* proc_from_elf (uint8_t* elf_contents); + struct proc* proc_clone (struct proc* proto, uintptr_t vstack_top, uintptr_t entry, uintptr_t argument_ptr); -void proc_cleanup (struct proc* proc); + +void proc_cleanup (struct proc* proc, struct reschedule_ctx* rctx); + void proc_init_tls (struct proc* proc); #endif // _KERNEL_SYS_PROC_H diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index a9622a3..c8cc62d 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -22,10 +22,9 @@ #include #define DEFINE_SYSCALL(name) \ - uintptr_t name (struct proc* UNUSED proc, void* UNUSED regs, bool* UNUSED reschedule, \ - struct cpu** UNUSED reschedule_cpu, uintptr_t UNUSED a1, uintptr_t UNUSED a2, \ - uintptr_t UNUSED a3, uintptr_t UNUSED a4, uintptr_t UNUSED a5, \ - uintptr_t UNUSED a6) + uintptr_t name (struct proc* UNUSED proc, void* UNUSED regs, struct reschedule_ctx* UNUSED rctx, \ + uintptr_t UNUSED a1, uintptr_t UNUSED a2, uintptr_t UNUSED a3, \ + uintptr_t UNUSED a4, uintptr_t UNUSED a5, uintptr_t UNUSED a6) #define SYSRESULT(x) ((uintptr_t)(x)) @@ -50,8 +49,7 @@ static void* sys_get_user_buffer (struct proc* proc, uintptr_t uvaddr, size_t si /* int quit (void) */ DEFINE_SYSCALL (sys_quit) { - if (proc_kill (proc, reschedule_cpu) == PROC_NEED_RESCHEDULE) - *reschedule = true; + proc_kill (proc, rctx); return SYSRESULT (ST_OK); } @@ -100,8 +98,7 @@ DEFINE_SYSCALL (sys_clone) { int pid = new->pid; - if (proc_register (new, reschedule_cpu) == PROC_NEED_RESCHEDULE) - *reschedule = true; + proc_register (new, NULL, rctx); return SYSRESULT (pid); } @@ -111,7 +108,7 @@ DEFINE_SYSCALL (sys_argument_ptr) { return proc->uvaddr_argument; } /* int sched (void) */ DEFINE_SYSCALL (sys_sched) { - *reschedule = true; + reschedule_list_append (rctx, thiscpu); return SYSRESULT (ST_OK); } @@ -136,8 +133,7 @@ DEFINE_SYSCALL (sys_mutex_delete) { if (mutex_resource == NULL) return SYSRESULT (-ST_NOT_FOUND); - if (proc_delete_resource (mutex_resource, reschedule_cpu) == PROC_NEED_RESCHEDULE) - *reschedule = true; + proc_delete_resource (mutex_resource, rctx); return SYSRESULT (ST_OK); } @@ -151,8 +147,7 @@ DEFINE_SYSCALL (sys_mutex_lock) { if (mutex_resource == NULL) return SYSRESULT (-ST_NOT_FOUND); - if (proc_mutex_lock (proc, &mutex_resource->u.mutex, reschedule_cpu) == PROC_NEED_RESCHEDULE) - *reschedule = true; + proc_mutex_lock (proc, &mutex_resource->u.mutex, rctx); return SYSRESULT (ST_OK); } @@ -166,8 +161,7 @@ DEFINE_SYSCALL (sys_mutex_unlock) { if (mutex_resource == NULL) return SYSRESULT (-ST_NOT_FOUND); - if (proc_mutex_unlock (proc, &mutex_resource->u.mutex, reschedule_cpu) == PROC_NEED_RESCHEDULE) - *reschedule = true; + proc_mutex_unlock (proc, &mutex_resource->u.mutex, rctx); return SYSRESULT (ST_OK); } @@ -193,10 +187,7 @@ DEFINE_SYSCALL (sys_mail_send) { if (mail_resource == NULL) return SYSRESULT (-ST_NOT_FOUND); - if (proc_mail_send (proc, &mail_resource->u.mail, reschedule_cpu, mesg, mesg_size) == - PROC_NEED_RESCHEDULE) { - *reschedule = true; - } + proc_mail_send (proc, &mail_resource->u.mail, rctx, mesg, mesg_size); return SYSRESULT (ST_OK); } @@ -216,10 +207,7 @@ DEFINE_SYSCALL (sys_mail_receive) { if (mail_resource == NULL) return SYSRESULT (-ST_NOT_FOUND); - if (proc_mail_receive (proc, &mail_resource->u.mail, reschedule_cpu, mesg, mesg_size) == - PROC_NEED_RESCHEDULE) { - *reschedule = true; - } + proc_mail_receive (proc, &mail_resource->u.mail, rctx, mesg, mesg_size); return SYSRESULT (ST_OK); } @@ -264,15 +252,9 @@ DEFINE_SYSCALL (sys_device_do) { if (device == NULL) return SYSRESULT (-ST_NOT_FOUND); - struct device_op_ctx op_ctx = { - .proc = proc, - .reschedule = reschedule, - .reschedule_cpu = reschedule_cpu, - }; - spin_lock (&device->lock); - int ret = device->ops[cmd](device, &op_ctx, (void*)ka1, (void*)ka2, (void*)ka3, (void*)ka4); + int ret = device->ops[cmd](device, proc, rctx, (void*)ka1, (void*)ka2, (void*)ka3, (void*)ka4); spin_unlock (&device->lock); @@ -310,8 +292,7 @@ DEFINE_SYSCALL (sys_exec) { int pid = new->pid; new->exec_pid = proc->pid; - if (proc_register (new, reschedule_cpu) == PROC_NEED_RESCHEDULE) - *reschedule = true; + proc_register (new, NULL, rctx); return SYSRESULT (pid); } @@ -441,6 +422,9 @@ DEFINE_SYSCALL (sys_get_procgroup) { struct proc* target_proc = proc_find_pid (pid); + if (target_proc == NULL) + return SYSRESULT (-ST_NOT_FOUND); + return SYSRESULT (target_proc->procgroup->pgid); } diff --git a/kernel/syscall/syscall.h b/kernel/syscall/syscall.h index 5953707..0aaacae 100644 --- a/kernel/syscall/syscall.h +++ b/kernel/syscall/syscall.h @@ -1,13 +1,15 @@ #ifndef _KERNEL_SYSCALL_SYSCALL_H #define _KERNEL_SYSCALL_SYSCALL_H +#include #include #include +#include struct cpu; -typedef uintptr_t (*syscall_handler_func_t) (struct proc* proc, void* regs, bool* reschedule, - struct cpu** reschedule_cpu, uintptr_t a1, +typedef uintptr_t (*syscall_handler_func_t) (struct proc* proc, void* regs, + struct reschedule_ctx* rctx, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6);