From 60fef5ac989b3d7d6e71baca5ca5cb7660eb4493 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 26 Jun 2026 00:00:00 +0000 Subject: [PATCH 01/65] [PROCESS] threading (limited to manual-scheduled threads) [INPUT] switched dispatch to C --- .../{input_dispatch.cpp => input_dispatch.c} | 12 +- kernel/process/loading/process_loader.c | 13 +- kernel/process/process.h | 27 +++- kernel/process/scheduler.c | 36 ++++- kernel/process/scheduler.h | 2 + kernel/process/signals/signals.c | 5 +- kernel/process/syscall.c | 133 ++++++++++-------- shared | 2 +- user/demo/default_process.c | 10 +- 9 files changed, 149 insertions(+), 91 deletions(-) rename kernel/input/{input_dispatch.cpp => input_dispatch.c} (88%) diff --git a/kernel/input/input_dispatch.cpp b/kernel/input/input_dispatch.c similarity index 88% rename from kernel/input/input_dispatch.cpp rename to kernel/input/input_dispatch.c index 33643e99..e28475d7 100644 --- a/kernel/input/input_dispatch.cpp +++ b/kernel/input/input_dispatch.c @@ -36,7 +36,7 @@ bool register_keypress(keypress kp) { } process_t *target = focused_proc; - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { u16 win_id = target ? target->win_id : 0; u16 skip_id = target ? target->id : 0; focused_proc = 0; @@ -47,7 +47,7 @@ bool register_keypress(keypress kp) { } target = focused_proc; - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { focused_proc = 0; return false; } @@ -83,7 +83,7 @@ bool register_scroll(i8 scroll){ void register_event(kbd_event event){ process_t *target = focused_proc; - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { u16 win_id = target ? target->win_id : 0; u16 skip_id = target ? target->id : 0; focused_proc = 0; @@ -94,7 +94,7 @@ void register_event(kbd_event event){ } target = focused_proc; - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { focused_proc = 0; return; } @@ -174,7 +174,7 @@ void sys_focus_current(){ void sys_set_focus(int pid){ process_t *target = get_proc_by_pid(pid); - if (!target || target->state == process::STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) return; + if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) return; if (focused_proc) focused_proc->focused = false; focused_proc = target; focused_proc->focused = true; @@ -192,7 +192,7 @@ void sys_unset_focus(bool close){ if (npid) { process_t *next = get_proc_by_pid(npid); - if (next && next->focused && next->state != process::STOPPED && next->id && next->pc && next->sp && ((((next->spsr & 0xF) != 0) || next->mm.ttbr0))) focused_proc = next; + if (next && next->focused && next->state != STOPPED && next->id && next->pc && next->sp && ((((next->spsr & 0xF) != 0) || next->mm.ttbr0))) focused_proc = next; } } diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index f14a608f..8a83f7fd 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -316,13 +316,8 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat } if (!shared_page) { shared_page = palloc_inner(PAGE_SIZE, MEM_PRIV_SHARED, MEM_EXEC, true, false); - if (!shared_page) { - pfree((void*)dmap_pa_to_kva(dest), code_size); - reset_process(proc); - return 0; - } - memset((void*)dmap_pa_to_kva(shared_page), 0, PAGE_SIZE); - *(uint32_t*)(uintptr_t)dmap_pa_to_kva(shared_page) = aarch64_svc(HALT_CODE); + *(u32*)(uptr)dmap_pa_to_kva(shared_page) = aarch64_svc(HALT_CODE); + *(u32*)(uptr)dmap_pa_to_kva(shared_page+sizeof(u32)) = aarch64_svc(HALT_THREAD_CODE); } // kprintf("Allocated space for process between %x and %x",dest,dest+((code_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))); @@ -394,7 +389,6 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->mm.stack_limit = stack_limit; proc->mm.stack_commit = stack_commit; - uint64_t total_pages = get_total_user_ram() / PAGE_SIZE; if (!total_pages) total_pages = 1; @@ -415,7 +409,8 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->pc = (uintptr_t)(entry); proc->regs[30] = shared_base; - kprintf("User process %s (%i) allocated at %llx entry=%llx stack=%llx-%llx (phys=%llx-%llx) anon=%llx (phys=%llx)", name, proc->id, proc, (uint64_t)proc->pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->stack_phys, (uint64_t)proc->stack_phys, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); + proc->shared_page = shared_base; + kprintf("%llx.User process %s (%i) allocated at %llx entry=%llx stack=%llx-%llx (phys=%llx-%llx) anon=%llx (phys=%llx)", shared_base, name, proc->id, proc, (uint64_t)proc->pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->stack_phys, (uint64_t)proc->stack_phys, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); proc->spsr = 0; proc->state = BLOCKED; diff --git a/kernel/process/process.h b/kernel/process/process.h index 13d37922..88f0fcb5 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -55,6 +55,20 @@ typedef struct { u64 fs_id; } system_permissions; +typedef enum { STOPPED, READY, RUNNING, BLOCKED } process_state; + +typedef struct { + uint64_t regs[31]; // x0–x30 + uintptr_t sp; + uintptr_t pc; + uint64_t spsr; + //Not used in process saving + uintptr_t stack; + uint64_t stack_size; + u16 pid; + process_state thread_state; +} thread_t; + typedef struct process { //We use the addresses of these variables to save and restore process state uint64_t regs[31]; // x0–x30 @@ -62,14 +76,15 @@ typedef struct process { uintptr_t pc; uint64_t spsr; //Not used in process saving + uintptr_t stack; + paddr_t stack_phys; + uint64_t stack_size; + //Thread ends uint16_t id; bool in_ready_queue; bool sleeping; bool suspended; uint64_t wake_at_msec; - uintptr_t stack; - paddr_t stack_phys; - uint64_t stack_size; paddr_t heap_phys; kaddr_t output; size_t output_size; @@ -85,13 +100,13 @@ typedef struct process { uaddr_t va; page_index *alloc_map; draw_ctx graphics_ctx; - enum process_state { STOPPED, READY, RUNNING, BLOCKED } state; + process_state state; __attribute__((aligned(16))) input_buffer_t input_buffer; __attribute__((aligned(16))) event_buffer_t event_buffer; __attribute__((aligned(16))) packet_buffer_t packet_buffer; __attribute__((aligned(16))) scroll_buffer_t scroll_buffer; __attribute__((aligned(16))) signal_buffer_t signal_buffer; - __attribute__((aligned(16))) signal_handler signal_handlers[NUMBER_SIGNALS]; + __attribute__((aligned(16))) thread_t signal_handlers[NUMBER_SIGNALS]; uint8_t priority; system_permissions permissions; uint16_t win_id; @@ -104,7 +119,9 @@ typedef struct process { sizedptr debug_line_str; system_module exposed_fs; mm_struct mm; + int thread_count; environment_data environment; + uptr shared_page; struct process *process_next; } process_t; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 615d2870..61a58c80 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -31,6 +31,8 @@ static process_t *process_list = 0; uint16_t proc_count = 0; uint16_t next_proc_index = 1; +#define is_privileged(spsr) (spsr & 0xf) + //TODO maybe use a weighted ready queue based on process priority CQueue ready_queue = {}; linked_list_t sleeping_list = {}; @@ -176,7 +178,7 @@ void process_restore(){ } panic("process_restore invalid process", cpec); } - if ((current_proc->spsr & 0xF) == 0) { + if (!is_privileged(current_proc->spsr)) { if (!current_proc->mm.ttbr0) panic("process_restore user process without ttbr0", cpec); if (current_proc->pc >= HIGH_VA) panic("user pc in kernel VA", current_proc->pc); mmu_ttbr0_enable_user(); @@ -185,8 +187,12 @@ void process_restore(){ signal_info_t *info = ¤t_proc->signal_buffer.entries[current_proc->signal_buffer.read_index];//TODO: Wrong, this should be copied into userland mem current_proc->signal_buffer.read_index = (current_proc->signal_buffer.read_index + 1) % INPUT_BUFFER_CAPACITY; if (can_signal_be_handled(info->type)){ - signal_handler handler = current_proc->signal_handlers[info->type]; - if (handler) handler(info); + thread_t *handler = ¤t_proc->signal_handlers[info->type]; + if (handler->pc){ + handler->spsr = current_proc->spsr; + cpec = (uptr)handler; + restore_context(cpec); + } else handle_signal_default(current_proc, info); } else handle_signal_default(current_proc, info); switch_proc(RECV_SIGNAL);//TODO: wasteful, we might have a lot of CPU time left for this proc to use @@ -364,7 +370,7 @@ void reset_process(process_t *proc){ fid = reserve_fd_gid(proc_path); module_file *state_file = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); if (state_file && (uintptr_t)state_file->file_buffer.buffer == (uintptr_t)&proc->state) { - enum process_state *snapshot = (enum process_state*)zalloc(sizeof(proc->state)); + process_state *snapshot = (process_state*)zalloc(sizeof(proc->state)); if (snapshot) { *snapshot = STOPPED; state_file->buf = (uptr)snapshot; @@ -699,6 +705,28 @@ void wake_processes(){ irq_restore(irq); } +sizedptr new_stack(process_t *proc){ + uptr stack_limit = (uptr)0x00008FFFFFFFF000ULL; + uptr stack_top = stack_limit - proc->stack_size; + mm_add_vma(&proc->mm, proc->mm.stack_top, stack_limit, MEM_RW, VMA_KIND_ANON, VMA_FLAG_DEMAND); + print("New stack at %llx-%llx",stack_limit,stack_top); + return (sizedptr){.ptr = stack_top, proc->stack_size}; +} + +thread_t new_thread(process_t *proc, uptr entry_point){ + sizedptr stack = new_stack(proc); + thread_t t = { + .pc = entry_point, + .pid = proc->id, + .regs = {}, + .sp = stack.ptr, + .stack_size = stack.size, + .spsr = proc->spsr + }; + t.regs[30] = proc->shared_page+sizeof(u32);//TODO: kernel processes don't have this + return t; +} + bool load_process_module(process_t *p, system_module *m){ p->exposed_fs = *m; p->exposed_fs.init = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.init - (uintptr_t)p->va)); diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 544eb930..5f83f2dc 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -61,6 +61,8 @@ bool get_current_privilege(); uint16_t process_count(); process_t *get_all_processes(); +thread_t new_thread(process_t *proc, uptr entry_point); + extern system_module scheduler_module; extern char ksp[]; diff --git a/kernel/process/signals/signals.c b/kernel/process/signals/signals.c index f686f1f6..02aa4d2d 100644 --- a/kernel/process/signals/signals.c +++ b/kernel/process/signals/signals.c @@ -5,7 +5,7 @@ #include "console/kio.h" bool register_signal_handler(process_t *proc, signal_types type, signal_handler handler){ - if (proc->signal_handlers[type]){ + if (proc->signal_handlers[type].pc){ kprint("Signal already exists"); return false; } @@ -14,8 +14,7 @@ bool register_signal_handler(process_t *proc, signal_types type, signal_handler return false; } kprint("Signal handler added"); - proc->signal_handlers[type] = handler; - //TODO: Can we check if the handler is in proc's va? cba rn + proc->signal_handlers[type] = new_thread(proc, (uptr)handler); return true; } diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 14f37a0e..dc410f80 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -39,24 +39,24 @@ int syscall_depth = 0; uintptr_t cpec; #define SYSCALL_STR(name, arg, write)\ - if (!ctx->arg) return 0;\ - char *name = (char*)ctx->arg;\ - if (!validate_address(ctx, ctx->arg, sizeof(name), write)) return 0; + char *name = (char*)current_thread->arg;\ + if (!name) return 0;\ + if (!validate_address(ctx, (uptr)name, sizeof(name), write)) return 0; #define SYSCALL_ARG(type, name, arg, write) \ - if (!ctx->arg) return 0;\ - type *name = (type*)ctx->arg;\ + type *name = (type*)current_thread->arg;\ + if (!name) return 0;\ if (!validate_address(ctx, (uptr)name, sizeof(type), write)) return 0;\ #define SYSCALL_ARG_SIZE(type, name, size, arg, write) \ - if (!ctx->arg && size) return 0;\ - type *name = (type*)ctx->arg;\ + type *name = (type*)current_thread->arg;\ + if (!name && size) return 0;\ if (!validate_address(ctx, (uptr)name, size, write)) return 0;\ //TEST: What happens if we pass another process' data in here? -typedef uint64_t (*syscall_entry)(process_t *ctx); +typedef uint64_t (*syscall_entry)(process_t *ctx, thread_t *current_thread); -uptr syscall_palloc(process_t *ctx){ +uptr syscall_palloc(process_t *ctx, thread_t *current_thread){ size_t size = ctx->PROC_X0; if(!size) return 0; u64 pages = count_pages(size, PAGE_SIZE); @@ -77,7 +77,7 @@ uptr syscall_palloc(process_t *ctx){ return (uptr)kva; } -u64 syscall_pfree(process_t *ctx){ +u64 syscall_pfree(process_t *ctx, thread_t *current_thread){ uptr va = ctx->PROC_X0; if (!va) return 0; @@ -111,35 +111,35 @@ u64 syscall_pfree(process_t *ctx){ return 0; } -u64 syscall_printl(process_t *ctx){ +u64 syscall_printl(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(str, PROC_X0, false); kprint((char*)str); return 0; } -u64 syscall_serial_transmit(process_t *ctx){//TODO: will probably require special permission +u64 syscall_serial_transmit(process_t *ctx, thread_t *current_thread){//TODO: will probably require special permission if (sys_get_focused_pid() != ctx->id) return 0; u8 byte = ctx->PROC_X0; if (byte) uart_raw_putc(byte); return 0; } -u64 syscall_read_key(process_t *ctx){ +u64 syscall_read_key(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(keypress, key, PROC_X0, true); return sys_read_input_current(key); } -u64 syscall_read_event(process_t *ctx){ +u64 syscall_read_event(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(kbd_event, ev, PROC_X0, true); return sys_read_event_current(ev); } -u64 syscall_read_shortcut(process_t *ctx){ +u64 syscall_read_shortcut(process_t *ctx, thread_t *current_thread){ kprint("[SYSCALL implementation error] Shortcut syscalls are not implemented yet"); return 0; } -u64 syscall_get_mouse(process_t *ctx){ +u64 syscall_get_mouse(process_t *ctx, thread_t *current_thread){ //TODO: we're not fully preventing the mouse from being read outside of proc's window (raw & buttons) if (sys_get_focused_pid() != ctx->id) return 0; SYSCALL_ARG(mouse_data, inp, PROC_X0, true); @@ -149,20 +149,20 @@ u64 syscall_get_mouse(process_t *ctx){ return 0; } -uptr syscall_gpu_request_ctx(process_t *ctx){ +uptr syscall_gpu_request_ctx(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(draw_ctx, win, PROC_X0, true); get_window_ctx(win); return 0; } -u64 syscall_gpu_flush(process_t *ctx){ +u64 syscall_gpu_flush(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(draw_ctx, win, PROC_X0, true); commit_frame(win, 0, false); gpu_flush(); return 0; } -u64 syscall_gpu_resize_ctx(process_t *ctx){ +u64 syscall_gpu_resize_ctx(process_t *ctx, thread_t *current_thread){ uint32_t width = (uint32_t)ctx->PROC_X1; uint32_t height = (uint32_t)ctx->PROC_X2; resize_window(width, height); @@ -172,29 +172,39 @@ u64 syscall_gpu_resize_ctx(process_t *ctx){ return 0; } -u64 syscall_char_size(process_t *ctx){ +u64 syscall_char_size(process_t *ctx, thread_t *current_thread){ return gpu_get_char_size(ctx->PROC_X0); } -u64 syscall_msleep(process_t *ctx){ +u64 syscall_msleep(process_t *ctx, thread_t *current_thread){ syscall_depth--; sleep_process(ctx->PROC_X0); return 0; } -u64 syscall_halt(process_t *ctx){ +u64 syscall_halt(process_t *ctx, thread_t *current_thread){ kprintf("Process has ended with code %i",ctx->PROC_X0); syscall_depth--; - stop_current_process(ctx->PROC_X0); + stop_current_process(current_thread->PROC_X0); return 0; } -u64 syscall_exec(process_t *ctx){ +u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ + kprintf("Thread has ended with code %i",current_thread->PROC_X0); + syscall_depth--; + if ((uptr)current_thread == (uptr)ctx) + stop_current_process(current_thread->PROC_X0); + else + switch_proc(YIELD); + return 0; +} + +u64 syscall_exec(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(prog_name, PROC_X0, false); //TODO: prog-name *might* need to be resolved in fs if it contains / - int argc = (int)ctx->PROC_X1; - uintptr_t uargv = (uintptr_t)ctx->PROC_X2; - uint32_t mode = (uint32_t)ctx->PROC_X3; + int argc = (int)current_thread->PROC_X1; + uintptr_t uargv = (uintptr_t)current_thread->PROC_X2; + uint32_t mode = (uint32_t)current_thread->PROC_X3; if (argc < 0 || argc > 64) return 0; @@ -208,7 +218,7 @@ u64 syscall_exec(process_t *ctx){ return p ? p->id : 0; } -u64 syscall_kill_process(process_t *ctx) { +u64 syscall_kill_process(process_t *ctx, thread_t *current_thread) { uint16_t pid = (uint16_t)ctx->PROC_X0; if (!pid) return 0; @@ -222,11 +232,11 @@ u64 syscall_kill_process(process_t *ctx) { return 0; } -u64 syscall_get_time(process_t *ctx){ +u64 syscall_get_time(process_t *ctx, thread_t *current_thread){ return timer_now_msec(); } -u64 syscall_socket_create(process_t *ctx){ +u64 syscall_socket_create(process_t *ctx, thread_t *current_thread){ Socket_Role role = (Socket_Role)ctx->PROC_X0; protocol_t protocol = (protocol_t)ctx->PROC_X1; SYSCALL_ARG(const SocketExtraOptions, extra, PROC_X2, false); @@ -235,14 +245,14 @@ u64 syscall_socket_create(process_t *ctx){ return create_socket(role, protocol, extra, ctx->id, out); } -u64 syscall_socket_bind(process_t *ctx){ +u64 syscall_socket_bind(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle,PROC_X0, true); ip_version_t ip_version = (ip_version_t)ctx->PROC_X1; uint16_t port = (uint16_t)ctx->PROC_X2; return bind_socket(handle, port, ip_version, ctx->id); } -u64 syscall_socket_connect(process_t *ctx){ +u64 syscall_socket_connect(process_t *ctx, thread_t *current_thread){ uint8_t dst_kind = (uint8_t)ctx->PROC_X1; uint16_t port = (uint16_t)ctx->PROC_X3; @@ -263,20 +273,20 @@ u64 syscall_socket_connect(process_t *ctx){ return connect_socket(handle, dst_kind, dst, port, ctx->id); } -u64 syscall_socket_listen(process_t *ctx){ +u64 syscall_socket_listen(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); int32_t backlog = (int32_t)ctx->PROC_X1; return listen_on(handle, backlog, ctx->id); } -u64 syscall_socket_accept(process_t *ctx){ +u64 syscall_socket_accept(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); accept_on_socket(handle, ctx->id); return 1; } -u64 syscall_socket_send(process_t *ctx){ +u64 syscall_socket_send(process_t *ctx, thread_t *current_thread){ uint8_t dst_kind = (uint8_t)ctx->PROC_X1; uint16_t port = (uint16_t)ctx->PROC_X3; size_t size = (size_t)ctx->regs[5]; @@ -305,7 +315,7 @@ u64 syscall_socket_send(process_t *ctx){ return send_on_socket(handle, dst_kind, dst, port, kbuf, size, ctx->id); } -u64 syscall_socket_receive(process_t *ctx){ +u64 syscall_socket_receive(process_t *ctx, thread_t *current_thread){ size_t size = (size_t)ctx->PROC_X2; if (!size) return 0; uint64_t alloc_size = (size + 0xFFF) & ~0xFFFULL; @@ -317,7 +327,7 @@ u64 syscall_socket_receive(process_t *ctx){ return receive_from_socket(handle, buf, size, src, ctx->id); } -u64 syscall_socket_close(process_t *ctx){ +u64 syscall_socket_close(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); return close_socket(handle, ctx->id); } @@ -325,7 +335,7 @@ u64 syscall_socket_close(process_t *ctx){ #define ISOLATEDFS #define ISOLATEDFS_ALLOW_KFS true -u64 syscall_openf(process_t *ctx){ +u64 syscall_openf(process_t *ctx, thread_t *current_thread){ #ifdef ISOLATEDFS SYSCALL_STR(path, PROC_X0, false); SYSCALL_ARG(file,descriptor,PROC_X1, true); @@ -347,21 +357,21 @@ u64 syscall_openf(process_t *ctx){ #endif } -u64 syscall_readf(process_t *ctx){ +u64 syscall_readf(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(file, descriptor, PROC_X0, true); size_t size = (size_t)ctx->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, true); return read_file(descriptor, buf, size); } -u64 syscall_writef(process_t *ctx){ +u64 syscall_writef(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(file, descriptor, PROC_X0, true); size_t size = (size_t)ctx->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, false); return write_file(descriptor, buf, size); } -u64 syscall_sreadf(process_t *ctx){ +u64 syscall_sreadf(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path, PROC_X0, false); size_t size = (size_t)ctx->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, false); @@ -377,7 +387,7 @@ u64 syscall_sreadf(process_t *ctx){ #endif } -u64 syscall_swritef(process_t *ctx){ +u64 syscall_swritef(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path, PROC_X0, false); size_t size = (size_t)ctx->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, false); @@ -394,13 +404,13 @@ u64 syscall_swritef(process_t *ctx){ #endif } -u64 syscall_closef(process_t *ctx){ +u64 syscall_closef(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(file,descriptor, PROC_X0, true); close_file(descriptor); return 0; } -u64 syscall_dir_list(process_t *ctx){ +u64 syscall_dir_list(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path,PROC_X0, false); size_t size = (size_t)ctx->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, true); @@ -426,7 +436,7 @@ u64 syscall_dir_list(process_t *ctx){ #endif } -u64 syscall_stat(process_t *ctx){ +u64 syscall_stat(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path,PROC_X0, false); SYSCALL_ARG(fs_stat,out_stat,PROC_X1, true); #ifdef ISOLATEDFS @@ -443,24 +453,22 @@ u64 syscall_stat(process_t *ctx){ #endif } -u64 syscall_trunc(process_t* ctx){ +u64 syscall_trunc(process_t* ctx, thread_t *current_thread){ SYSCALL_ARG(file,descriptor,PROC_X0, true); size_t size = ctx->PROC_X1; return truncate(descriptor, size); } -u64 syscall_signal_send(process_t* ctx){ +u64 syscall_signal_send(process_t* ctx, thread_t *current_thread){ signal_types type = ctx->PROC_X0; u16 proc_id = ctx->PROC_X1; return send_signal_proc_id(type, 0, ctx, proc_id); } -u64 syscall_signal_handler(process_t* ctx){ - kprint("[SYSCALL implementation error] syscall handlers are not supported in userspace yet"); - //TODO: for this and FS modules, we'll need to set up an isolated environment (thread-like) for them to run in - return 0; +u64 syscall_signal_handler(process_t* ctx, thread_t *current_thread){ signal_types type = ctx->PROC_X0; uptr handler = ctx->PROC_X1; + print("Handler is %x",handler); if (!handler) return 0; if (!validate_address(ctx, handler, sizeof(uptr), false)) return 0; return register_signal_handler(ctx, type, (signal_handler)handler); @@ -475,7 +483,7 @@ u64 syscall_signal_handler(process_t* ctx){ // return unload_module(&ctx->exposed_fs); // } -u64 syscall_in_case_of_js(process_t *ctx){ +u64 syscall_in_case_of_js(process_t *ctx, thread_t *current_thread){ panic("Shame on you\r\n\ Don't ever do that again\r\n\ ....................../'¯/) \r\n\ @@ -506,6 +514,7 @@ syscall_entry syscalls[] = { [RESIZE_DRAW_CTX_CODE] = syscall_gpu_resize_ctx, [SLEEP_CODE] = syscall_msleep, [HALT_CODE] = syscall_halt, + [HALT_THREAD_CODE] = syscall_halt_thread, [EXEC_CODE] = syscall_exec, [KILL_PROCESS_CODE] = syscall_kill_process, [GET_TIME_CODE] = syscall_get_time, @@ -618,7 +627,6 @@ void coredump(uintptr_t esr, uintptr_t elr, uintptr_t far, uintptr_t sp){ void sync_el0_handler_c(){ save_return_address_interrupt(); - mmu_ttbr0_disable_user(); syscall_depth++; #if TEST @@ -653,7 +661,8 @@ void sync_el0_handler_c(){ if (ec == 0x15) { syscall_entry entry = syscalls[iss]; if (entry){ - result = entry(proc); + thread_t *current_thread = (thread_t*)cpec; + result = entry(proc, current_thread); } else { kprintf("Unknown syscall in process. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); coredump(esr, elr, far, proc->sp); @@ -662,14 +671,14 @@ void sync_el0_handler_c(){ } } else { if (currentEL == 1){ - if (syscall_depth < 3){ - kprintf("System has crashed. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); - uint64_t ksp = 0; - asm volatile ("mov %0, sp" : "=r"(ksp)); - coredump(esr, elr, far, ksp); - } - handle_exception("UNEXPECTED EXCEPTION", ec); - while (true); + if (syscall_depth < 3){ + kprintf("System has crashed. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); + uint64_t ksp = 0; + asm volatile ("mov %0, sp" : "=r"(ksp)); + coredump(esr, elr, far, ksp); + } + handle_exception("UNEXPECTED EXCEPTION", ec); + while (true); } else { kprintf("Process has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", esr, elr, far, proc->sp); if (syscall_depth <= 2) coredump(esr, elr, far, proc->sp); diff --git a/shared b/shared index c8ff6193..6a9886d8 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit c8ff6193b2bdce49d5e09a8eb8913cbd14cc31b3 +Subproject commit 6a9886d8c17551b1f16d4eb9a9711537992b48f8 diff --git a/user/demo/default_process.c b/user/demo/default_process.c index 21713a24..3a439f4e 100644 --- a/user/demo/default_process.c +++ b/user/demo/default_process.c @@ -186,8 +186,9 @@ int copypaste(){ bool should_quit = false; bool on_quit(signal_info_t *do_not_use_this){ - print("I'm told to quit"); + printl("I'm told to quit"); should_quit = true; + // while(true); return true; } @@ -202,6 +203,9 @@ struct { char* name; int (*fn)(); } demos[] = { }; int main(int argc, char* argv[]){ + + handle_signal(SIG_QUIT, on_quit); + send_signal(SIG_QUIT, 7); request_draw_ctx(&ctx); @@ -231,6 +235,10 @@ int main(int argc, char* argv[]){ while (true) { commit_draw_ctx(&ctx); + if (should_quit) { + print("SIG QUIT"); + halt(0); + } kbd_event ev = {}; if (read_event(&ev)){ if (ev.type == KEY_PRESS){ From ca8f0f34b4e3dfe40fa9532eaee45df9cb39e392 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 26 Jun 2026 00:00:00 +0000 Subject: [PATCH 02/65] [SYSCALL] current thread to get non-ptr types --- kernel/process/syscall.c | 62 ++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index dc410f80..b5f4cd72 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -57,7 +57,7 @@ uintptr_t cpec; typedef uint64_t (*syscall_entry)(process_t *ctx, thread_t *current_thread); uptr syscall_palloc(process_t *ctx, thread_t *current_thread){ - size_t size = ctx->PROC_X0; + size_t size = current_thread->PROC_X0; if(!size) return 0; u64 pages = count_pages(size, PAGE_SIZE); size_t alloc_size = pages * PAGE_SIZE; @@ -78,7 +78,7 @@ uptr syscall_palloc(process_t *ctx, thread_t *current_thread){ } u64 syscall_pfree(process_t *ctx, thread_t *current_thread){ - uptr va = ctx->PROC_X0; + uptr va = current_thread->PROC_X0; if (!va) return 0; if (ctx->mm.ttbr0) { @@ -119,7 +119,7 @@ u64 syscall_printl(process_t *ctx, thread_t *current_thread){ u64 syscall_serial_transmit(process_t *ctx, thread_t *current_thread){//TODO: will probably require special permission if (sys_get_focused_pid() != ctx->id) return 0; - u8 byte = ctx->PROC_X0; + u8 byte = current_thread->PROC_X0; if (byte) uart_raw_putc(byte); return 0; } @@ -163,8 +163,8 @@ u64 syscall_gpu_flush(process_t *ctx, thread_t *current_thread){ } u64 syscall_gpu_resize_ctx(process_t *ctx, thread_t *current_thread){ - uint32_t width = (uint32_t)ctx->PROC_X1; - uint32_t height = (uint32_t)ctx->PROC_X2; + uint32_t width = (uint32_t)current_thread->PROC_X1; + uint32_t height = (uint32_t)current_thread->PROC_X2; resize_window(width, height); SYSCALL_ARG(draw_ctx, win, PROC_X0, true); get_window_ctx(win); @@ -173,17 +173,17 @@ u64 syscall_gpu_resize_ctx(process_t *ctx, thread_t *current_thread){ } u64 syscall_char_size(process_t *ctx, thread_t *current_thread){ - return gpu_get_char_size(ctx->PROC_X0); + return gpu_get_char_size(current_thread->PROC_X0); } u64 syscall_msleep(process_t *ctx, thread_t *current_thread){ syscall_depth--; - sleep_process(ctx->PROC_X0); + sleep_process(current_thread->PROC_X0);//TODO: sleep thread instead return 0; } u64 syscall_halt(process_t *ctx, thread_t *current_thread){ - kprintf("Process has ended with code %i",ctx->PROC_X0); + kprintf("Process has ended with code %i",current_thread->PROC_X0); syscall_depth--; stop_current_process(current_thread->PROC_X0); return 0; @@ -219,7 +219,7 @@ u64 syscall_exec(process_t *ctx, thread_t *current_thread){ } u64 syscall_kill_process(process_t *ctx, thread_t *current_thread) { - uint16_t pid = (uint16_t)ctx->PROC_X0; + uint16_t pid = (uint16_t)current_thread->PROC_X0; if (!pid) return 0; process_t *target = get_proc_by_pid(pid); @@ -237,8 +237,8 @@ u64 syscall_get_time(process_t *ctx, thread_t *current_thread){ } u64 syscall_socket_create(process_t *ctx, thread_t *current_thread){ - Socket_Role role = (Socket_Role)ctx->PROC_X0; - protocol_t protocol = (protocol_t)ctx->PROC_X1; + Socket_Role role = (Socket_Role)current_thread->PROC_X0; + protocol_t protocol = (protocol_t)current_thread->PROC_X1; SYSCALL_ARG(const SocketExtraOptions, extra, PROC_X2, false); SYSCALL_ARG(SocketHandle, out, PROC_X3, true); @@ -247,14 +247,14 @@ u64 syscall_socket_create(process_t *ctx, thread_t *current_thread){ u64 syscall_socket_bind(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle,PROC_X0, true); - ip_version_t ip_version = (ip_version_t)ctx->PROC_X1; - uint16_t port = (uint16_t)ctx->PROC_X2; + ip_version_t ip_version = (ip_version_t)current_thread->PROC_X1; + uint16_t port = (uint16_t)current_thread->PROC_X2; return bind_socket(handle, port, ip_version, ctx->id); } u64 syscall_socket_connect(process_t *ctx, thread_t *current_thread){ - uint8_t dst_kind = (uint8_t)ctx->PROC_X1; - uint16_t port = (uint16_t)ctx->PROC_X3; + uint8_t dst_kind = (uint8_t)current_thread->PROC_X1; + uint16_t port = (uint16_t)current_thread->PROC_X3; SYSCALL_ARG(SocketHandle,handle,PROC_X0,true); @@ -275,7 +275,7 @@ u64 syscall_socket_connect(process_t *ctx, thread_t *current_thread){ u64 syscall_socket_listen(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); - int32_t backlog = (int32_t)ctx->PROC_X1; + int32_t backlog = (int32_t)current_thread->PROC_X1; return listen_on(handle, backlog, ctx->id); } @@ -287,8 +287,8 @@ u64 syscall_socket_accept(process_t *ctx, thread_t *current_thread){ } u64 syscall_socket_send(process_t *ctx, thread_t *current_thread){ - uint8_t dst_kind = (uint8_t)ctx->PROC_X1; - uint16_t port = (uint16_t)ctx->PROC_X3; + uint8_t dst_kind = (uint8_t)current_thread->PROC_X1; + uint16_t port = (uint16_t)current_thread->PROC_X3; size_t size = (size_t)ctx->regs[5]; SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); @@ -316,7 +316,7 @@ u64 syscall_socket_send(process_t *ctx, thread_t *current_thread){ } u64 syscall_socket_receive(process_t *ctx, thread_t *current_thread){ - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; if (!size) return 0; uint64_t alloc_size = (size + 0xFFF) & ~0xFFFULL; @@ -359,21 +359,21 @@ u64 syscall_openf(process_t *ctx, thread_t *current_thread){ u64 syscall_readf(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(file, descriptor, PROC_X0, true); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, true); return read_file(descriptor, buf, size); } u64 syscall_writef(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(file, descriptor, PROC_X0, true); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, false); return write_file(descriptor, buf, size); } u64 syscall_sreadf(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path, PROC_X0, false); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, false); #ifdef ISOLATEDFS module_root rootfs = {}; @@ -389,9 +389,9 @@ u64 syscall_sreadf(process_t *ctx, thread_t *current_thread){ u64 syscall_swritef(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path, PROC_X0, false); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, false); - bool append = (bool)ctx->PROC_X3; + bool append = (bool)current_thread->PROC_X3; #ifdef ISOLATEDFS module_root rootfs = {}; string s = resolve_isolated_path(path, ctx->permissions.fs_id, &rootfs, ISOLATEDFS_ALLOW_KFS); @@ -412,7 +412,7 @@ u64 syscall_closef(process_t *ctx, thread_t *current_thread){ u64 syscall_dir_list(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path,PROC_X0, false); - size_t size = (size_t)ctx->PROC_X2; + size_t size = (size_t)current_thread->PROC_X2; SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, true); SYSCALL_ARG(u64,offset,PROC_X3, true); #ifdef ISOLATEDFS @@ -455,19 +455,19 @@ u64 syscall_stat(process_t *ctx, thread_t *current_thread){ u64 syscall_trunc(process_t* ctx, thread_t *current_thread){ SYSCALL_ARG(file,descriptor,PROC_X0, true); - size_t size = ctx->PROC_X1; + size_t size = current_thread->PROC_X1; return truncate(descriptor, size); } u64 syscall_signal_send(process_t* ctx, thread_t *current_thread){ - signal_types type = ctx->PROC_X0; - u16 proc_id = ctx->PROC_X1; + signal_types type = current_thread->PROC_X0; + u16 proc_id = current_thread->PROC_X1; return send_signal_proc_id(type, 0, ctx, proc_id); } u64 syscall_signal_handler(process_t* ctx, thread_t *current_thread){ - signal_types type = ctx->PROC_X0; - uptr handler = ctx->PROC_X1; + signal_types type = current_thread->PROC_X0; + uptr handler = current_thread->PROC_X1; print("Handler is %x",handler); if (!handler) return 0; if (!validate_address(ctx, handler, sizeof(uptr), false)) return 0; @@ -475,7 +475,7 @@ u64 syscall_signal_handler(process_t* ctx, thread_t *current_thread){ } // uint64_t syscall_load_fsmod(process_t *ctx){ -// system_module *mod = (system_module*)ctx->PROC_X0; +// system_module *mod = (system_module*)current_thread->PROC_X0; // return load_process_module(ctx,mod); // } From e392702844da5caaaf9c15faaad4cbeff15006d8 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 26 Jun 2026 00:00:00 +0000 Subject: [PATCH 03/65] [PROCFS] moved to own file --- kernel/kernel.c | 2 +- kernel/kernel_processes/kprocess_loader.c | 9 +- kernel/kernel_processes/kprocess_loader.h | 2 + kernel/process/loading/process_loader.c | 2 +- kernel/process/procfs.c | 375 +++++++++++++++++++++ kernel/process/procfs.h | 5 + kernel/process/scheduler.c | 383 +--------------------- kernel/process/scheduler.h | 3 +- kernel/process/syscall.c | 2 +- user/demo/default_process.c | 1 + 10 files changed, 408 insertions(+), 376 deletions(-) create mode 100644 kernel/process/procfs.c create mode 100644 kernel/process/procfs.h diff --git a/kernel/kernel.c b/kernel/kernel.c index 5783f7cd..8877b9af 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -112,7 +112,7 @@ void kernel_main(uint64_t board_type, uint64_t dtb_pa) { load_module(&tool_module); - load_module(&scheduler_module); + init_scheduler(); load_module(&environment_module); diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index 5aef1e31..d7a85be2 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -9,9 +9,14 @@ #include "memory/memory.h" #include "process/isolated_fs/isolated_fs.h" -__attribute__((noreturn)) static void kernel_process_return_trampoline(int32_t exit_code) { +void kernel_thread_return_trampoline(int32_t exit_code){ + switch_proc(YIELD);//TODO: proper cleanup + while (true){} +} + +void kernel_process_return_trampoline(int32_t exit_code) { stop_current_process(exit_code); - while (1) {} + while (true) {} } process_t *create_kernel_process(const char *name, int (*func)(int argc, char* argv[]), int argc, const char* argv[]){ diff --git a/kernel/kernel_processes/kprocess_loader.h b/kernel/kernel_processes/kprocess_loader.h index 62b05b4d..25b45920 100644 --- a/kernel/kernel_processes/kprocess_loader.h +++ b/kernel/kernel_processes/kprocess_loader.h @@ -8,6 +8,8 @@ extern "C" { #include "process/process.h" process_t *create_kernel_process(const char *name, int (*func)(int argc, char* argv[]), int argc, const char* argv[]); +__attribute__((noreturn)) void kernel_thread_return_trampoline(int32_t exit_code); +__attribute__((noreturn)) void kernel_process_return_trampoline(int32_t exit_code); #ifdef __cplusplus } diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index 8a83f7fd..a8e09cca 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -410,7 +410,7 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->pc = (uintptr_t)(entry); proc->regs[30] = shared_base; proc->shared_page = shared_base; - kprintf("%llx.User process %s (%i) allocated at %llx entry=%llx stack=%llx-%llx (phys=%llx-%llx) anon=%llx (phys=%llx)", shared_base, name, proc->id, proc, (uint64_t)proc->pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->stack_phys, (uint64_t)proc->stack_phys, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); + kprintf("User process %s (%i) allocated at %llx entry=%llx stack=%llx-%llx (phys=%llx-%llx) anon=%llx (phys=%llx)", name, proc->id, proc, (uint64_t)proc->pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->stack_phys, (uint64_t)proc->stack_phys, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); proc->spsr = 0; proc->state = BLOCKED; diff --git a/kernel/process/procfs.c b/kernel/process/procfs.c new file mode 100644 index 00000000..a5f63293 --- /dev/null +++ b/kernel/process/procfs.c @@ -0,0 +1,375 @@ +#include "procfs.h" +#include "files/dir_list.h" +#include "process.h" +#include "exceptions/irq.h" +#include "console/kio.h" +#include "scheduler.h" +#include "math/math.h" + +extern process_t *process_list; +hash_map_t *proc_opened_files; + +typedef struct { + process_t *proc; + uint16_t pid; +} procfs_owner; + +void* proc_page; + +void* procfs_alloc(size_t size){ + return allocate(proc_page, size, page_alloc); +} + +bool init_procfs(){ + proc_page = page_alloc(PAGE_SIZE*16); + if (!proc_opened_files) { + proc_opened_files = hash_map_create(1024); + proc_opened_files->free = release; + proc_opened_files->alloc = procfs_alloc; + } + return true; +} + +size_t list_processes(void *buf, size_t size, file_offset *offset){ + + if (!buf || !offset || size < sizeof(uint32_t)) return 0; + + fs_dir_list_helper helper = create_dir_list_helper(buf, size); + + process_t *proc = process_list; + if (*offset) { + while (proc && proc->id != *offset) proc = proc->process_next; + } + + while (proc) { + if (proc->id != 0 && proc->state != STOPPED) { + char name[6]; + string_format_buf(name, 6, "%i", proc->id); + + if (!dir_list_fill(&helper, name)){ + if (offset){ + *offset = proc->id; + return dir_buf_size(&helper); + } + } + } + proc = proc->process_next; + } + + return dir_buf_size(&helper); +} + +#define NUM_PROC_FILES 2 + +char* proc_files[NUM_PROC_FILES] = { + "out", + "state" +}; + +size_t list_proc_files(void *buf, size_t size, file_offset *offset){ + + if (!buf || !offset || size < sizeof(uint32_t)) return 0; + + fs_dir_list_helper helper = create_dir_list_helper(buf, size); + + u64 index = offset ? *offset : 0; + + for (int i = index; i < NUM_PROC_FILES; i++){ + kprint(proc_files[i]); + char *name = (char*)((uptr)helper.list + 4 + helper.offset); + if (!dir_list_fill(&helper, proc_files[i])){ + if (offset) *offset = i; + return dir_buf_size(&helper); + } + kprint(name); + } + return dir_buf_size(&helper); +} + +size_t readdir_proc(const char *path, void *buf, size_t size, file_offset *offset){ + irq_flags_t irq = irq_save_disable(); + if (!strlen(path)){ + size_t res = list_processes(buf, size, offset); + irq_restore(irq); + return res; + } + const char *pid_s = seek_to(path, '/'); + path = seek_to(pid_s, '/'); + uint64_t pid = parse_int_u64(pid_s, path - pid_s); + process_t *proc = get_proc_by_pid(pid); + if (!proc) { + irq_restore(irq); + return false; + } + if (!strlen(path)){ + size_t res = list_proc_files(buf, size, offset); + irq_restore(irq); + return res; + } + irq_restore(irq); + return false; +} + +FS_RESULT open_proc(const char *path, file *descriptor){ + uint64_t fid = reserve_fd_gid(path); + irq_flags_t irq = irq_save_disable(); + module_file *mfile = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(uint64_t)); + if (mfile){ + descriptor->id = mfile->fid; + descriptor->size = mfile->file_size; + descriptor->cursor = 0; + mfile->references++; + procfs_owner *owner_info = (procfs_owner*)mfile->private_data; + if (owner_info && owner_info->proc && owner_info->proc->id == owner_info->pid) owner_info->proc->procfs_refs++; + irq_restore(irq); + return FS_RESULT_SUCCESS; + } + const char *pid_s = seek_to(path, '/'); + path = seek_to(pid_s, '/'); + uint64_t pid = parse_int_u64(pid_s, path - pid_s); + process_t *proc = get_proc_by_pid(pid); + if (!proc) { + irq_restore(irq); + return FS_RESULT_NOTFOUND; + } + descriptor->id = fid; + descriptor->cursor = 0; + module_file *file = procfs_alloc(sizeof(module_file)); + if (!file) { + irq_restore(irq); + return FS_RESULT_DRIVER_ERROR; + } + procfs_owner *owner_info = procfs_alloc(sizeof(procfs_owner)); + if (!owner_info) { + irq_restore(irq); + release(file); + return FS_RESULT_DRIVER_ERROR; + } + owner_info->proc = proc; + owner_info->pid = proc->id; + file->fid = fid; + file->private_data = owner_info; + file->references = 1; + if (strcmp_case(path, "out",true) == 0){ + descriptor->size = proc->output ? proc->output_size : proc->postmortem_output_size; + file->read_only = true; + file->buf = (uptr)(proc->output ? proc->output : proc->postmortem_output); + file->file_buffer = (buffer){ + .buffer = (char*)(proc->output ? proc->output : proc->postmortem_output), + .buffer_size = proc->output ? proc->output_size : proc->postmortem_output_size, + .limit = proc->output ? PROC_OUT_BUF : proc->postmortem_output_size, + .options = proc->output ? buffer_circular : buffer_static, + .cursor = proc->output ? proc->output_size : 0, + }; + proc->procfs_refs++; + } else if (strcmp_case(path, "state",true) == 0){ + descriptor->size = sizeof(proc->state); + file->read_only = true; + file->buf = (uptr)&proc->state; + file->file_buffer = (buffer){ + .buffer = (char*)&proc->state, + .limit = sizeof(proc->state), + .options = buffer_static, + .buffer_size = sizeof(proc->state), + .cursor = 0, + }; + proc->procfs_refs++; + } else { + irq_restore(irq); + release((void*)owner_info); + release(file); + return FS_RESULT_NOTFOUND; + } + file->file_size = descriptor->size; + int put = hash_map_put(proc_opened_files, &descriptor->id, sizeof(uint64_t), file); + irq_restore(irq); + if (put >= 0) return FS_RESULT_SUCCESS; + if ((uintptr_t)file->file_buffer.buffer == (uintptr_t)proc->output || (uintptr_t)file->file_buffer.buffer == (uintptr_t)proc->postmortem_output || (uintptr_t)file->file_buffer.buffer == (uintptr_t)&proc->state) { + if (proc->procfs_refs) proc->procfs_refs--; + } + release((void*)owner_info); + release(file); + return FS_RESULT_DRIVER_ERROR; +} + +bool stat_proc(const char *path, fs_stat *out_stat){ + if (!out_stat) return false; + irq_flags_t irq = irq_save_disable(); + if (!strlen(path)){ + bool res = stat_dir(out_stat); + irq_restore(irq); + return res; + } + const char *pid_s = seek_to(path, '/'); + path = seek_to(pid_s, '/'); + uint64_t pid = parse_int_u64(pid_s, path - pid_s); + process_t *proc = get_proc_by_pid(pid); + if (!proc) { + irq_restore(irq); + return false; + } + if (!strlen(path)){ + bool res = stat_dir(out_stat); + irq_restore(irq); + return res; + } + out_stat->type = entry_file; + if (strcmp_case(path, "out",true) == 0){ + out_stat->size = proc->output_size; + out_stat->data_type = DATA_SIG_TEXT; + } + if (strcmp_case(path, "state",true) == 0){ + out_stat->size = sizeof(proc->state); + out_stat->data_type = DATA_SIG_PROC_ST; + } + irq_restore(irq); + return true; +} + +int find_open_proc_file(void *node, void* key){ + uint64_t *fid = (uint64_t*)key; + module_file *file = (module_file*)node; + if (file->fid == *fid) return 0; + return -1; +} + +int find_open_proc_file_buffer(void *node, void* key){ + uintptr_t *buf = (uintptr_t*)key; + module_file *file = (module_file*)node; + if ((uintptr_t)file->file_buffer.buffer == *buf) return 0; + return -1; +} + +size_t read_proc(file* fd, char *buf, size_t size, file_offset offset){ + if (!proc_opened_files){ + kprint("No files open"); + return 0; + } + irq_flags_t irq = irq_save_disable(); + module_file *file = (module_file*)hash_map_get(proc_opened_files, &fd->id, sizeof(uint64_t)); + if (!file) { + irq_restore(irq); + return 0; + } + size_t s = buffer_read(&file->file_buffer, buf, size, offset); + fd->size = file->file_size; + irq_restore(irq); + return s; +} + +size_t write_proc(file* fd, const char *buf, size_t size, file_offset offset){ + process_t *proc = get_current_proc(); + if (fd->id == FD_OUT){ + if (!proc || !size) return 0; + if (!proc->output) { + proc->output = (kaddr_t)palloc(PROC_OUT_BUF, MEM_PRIV_KERNEL, MEM_RW, true); + if (!proc->output) return 0; + } + irq_flags_t irq = irq_save_disable(); + + buffer file_buffer = { + .buffer = (char*)proc->output, + .buffer_size = proc->output_size, + .limit = PROC_OUT_BUF, + .options = buffer_circular, + .cursor = proc->output_size, + }; + + size = min(size, file_buffer.limit); + size_t written = buffer_write_lim(&file_buffer, buf, size); + + proc->output_size = file_buffer.buffer_size; + fd->size = proc->output_size; + + if (proc_opened_files){ + char fullpath[48] = {}; + string_format_buf(fullpath, sizeof(fullpath), "/%i/out", proc->id); + uint64_t fid = reserve_fd_gid(fullpath); + module_file *file = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); + if (file) { + file->buf = (uptr)proc->output; + file->file_buffer.buffer = (char*)proc->output; + file->file_buffer.buffer_size = proc->output_size; + file->file_buffer.limit = PROC_OUT_BUF; + file->file_buffer.cursor = proc->output_size; + file->file_buffer.options = buffer_circular; + file->file_size = proc->output_size; + } + } + + irq_restore(irq); + return written; + } + + if (!proc_opened_files){ + kprint("No files open"); + return 0; + } + irq_flags_t irq = irq_save_disable(); + module_file *file = (module_file*)hash_map_get(proc_opened_files, &fd->id, sizeof(uint64_t)); + bool ro = file && file->read_only; + irq_restore(irq); + if (!file) return 0; + if (ro) return 0; + return 0; +} + +extern bool process_can_reset(process_t *proc); +extern bool process_has_runtime_state(process_t *proc); + +void close_proc(file *fd) { + if (!fd) return; + if (!proc_opened_files) return; + + uint64_t fid = fd->id; + process_t *reset_proc = 0; + irq_flags_t irq = irq_save_disable(); + module_file *mfile = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); + if (!mfile) { + irq_restore(irq); + return; + } + + procfs_owner *owner_info = (procfs_owner*)mfile->private_data; + process_t *owner = 0; + if (owner_info && owner_info->proc && owner_info->proc->id == owner_info->pid) owner = owner_info->proc; + if (owner) { + if (owner->procfs_refs) owner->procfs_refs--; + if (process_can_reset(owner) && process_has_runtime_state(owner)) reset_proc = owner; + } + + if (mfile->references > 0) mfile->references--; + if (mfile->references == 0) { + void *owned = mfile->file_buffer.buffer; + buffer_options options = mfile->file_buffer.options; + bool owned_postmortem = owner && owned == (void*)owner->postmortem_output; + hash_map_remove(proc_opened_files, &fid, sizeof(fid), 0); + irq_restore(irq); + if (owned && options == buffer_opt_none && !(reset_proc && owned_postmortem)) { + release(owned); + if (owned_postmortem) { + owner->postmortem_output = 0; + owner->postmortem_output_size = 0; + } + } + if (mfile->private_data) release(mfile->private_data); + release(mfile); + if (reset_proc) reset_process(reset_proc); + return; + } + irq_restore(irq); +} + +system_module procfs_mod = (system_module){ + .name = "scheduler", + .mount = "proc", + .version = VERSION_NUM(0, 1, 0, 1), + .init = init_procfs, + .fini = 0, + .open = open_proc, + .read = read_proc, + .write = write_proc, + .close = close_proc, + .getstat = stat_proc, + .readdir = readdir_proc, +}; diff --git a/kernel/process/procfs.h b/kernel/process/procfs.h new file mode 100644 index 00000000..4949e529 --- /dev/null +++ b/kernel/process/procfs.h @@ -0,0 +1,5 @@ +#pragma once + +#include "files/system_module.h" + +extern system_module procfs_mod; \ No newline at end of file diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 61a58c80..ab9e9dc3 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -27,7 +27,7 @@ extern void restore_context(uintptr_t ptr); static process_t *current_proc = 0; static process_t *kernel_proc = 0; static process_t *idle_proc = 0; -static process_t *process_list = 0; +process_t *process_list = 0; uint16_t proc_count = 0; uint16_t next_proc_index = 1; @@ -37,23 +37,16 @@ uint16_t next_proc_index = 1; CQueue ready_queue = {}; linked_list_t sleeping_list = {}; -hash_map_t *proc_opened_files; +extern hash_map_t *proc_opened_files; -void* proc_page; - -typedef struct { - process_t *proc; - uint16_t pid; -} procfs_owner; - -__attribute__((noreturn)) static void idle_entry() { +__attribute__((noreturn)) void idle_entry() { for (;;) { asm volatile("dsb sy" ::: "memory"); asm volatile("wfi"); } } -static bool process_is_known(process_t *proc){ +bool process_is_known(process_t *proc){ if (!proc) return false; if (proc == idle_proc) return true; process_t *it = process_list; @@ -64,23 +57,23 @@ static bool process_is_known(process_t *proc){ return false; } -static bool process_has_runtime_state(process_t *proc){ +bool process_has_runtime_state(process_t *proc){ return proc && (proc->sp || proc->pc || proc->spsr || proc->stack || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); } -static bool process_can_run(process_t *proc){ +bool process_can_run(process_t *proc){ if (!proc) return false; if (!process_is_known(proc) || proc->pending_reset) return false; if (proc->state == STOPPED || proc->sleeping || proc->suspended || !proc->pc || !proc->sp) return false; - if ((proc->spsr & 0xF) == 0) return !!proc->mm.ttbr0; + if (!is_privileged(proc->spsr)) return !!proc->mm.ttbr0; return !proc->mm.ttbr0; } -static bool process_can_reset(process_t *proc){ +bool process_can_reset(process_t *proc){ return proc && proc->state == STOPPED && proc->pending_reset && !proc->procfs_refs; } -static void enqueue_ready_process(process_t *proc){ +void enqueue_ready_process(process_t *proc){ if (!proc || proc == idle_proc || proc->in_ready_queue) return; if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); if (!cqueue_enqueue(&ready_queue, &proc)) panic("ready enqueue failed", proc->id); @@ -88,7 +81,7 @@ static void enqueue_ready_process(process_t *proc){ proc->state = READY; } -static bool remove_sleeping_process(process_t *proc, uint16_t pid){ +bool remove_sleeping_process(process_t *proc, uint16_t pid){ bool removed = false; linked_list_node_t *sleep = sleeping_list.head; while (sleep) { @@ -209,17 +202,9 @@ bool start_scheduler(){ return true; } -void* procfs_alloc(size_t size){ - return allocate(proc_page, size, page_alloc); -} - -bool init_scheduler_module(){ - if (!proc_opened_files) { - proc_opened_files = hash_map_create(1024); - proc_opened_files->free = release; - proc_opened_files->alloc = procfs_alloc; - } +bool init_scheduler(){ if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); + load_module(&procfs_mod); return true; } @@ -470,7 +455,6 @@ void reset_process(process_t *proc){ } void init_main_process(){ - proc_page = page_alloc(PAGE_SIZE*16); if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); size_t kernel_proc_size = (sizeof(process_t) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); kernel_proc = (process_t*)palloc(kernel_proc_size, MEM_PRIV_KERNEL, MEM_RW, true); @@ -723,7 +707,7 @@ thread_t new_thread(process_t *proc, uptr entry_point){ .stack_size = stack.size, .spsr = proc->spsr }; - t.regs[30] = proc->shared_page+sizeof(u32);//TODO: kernel processes don't have this + t.regs[30] = is_privileged(proc->spsr) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32);//TODO: kernel processes don't have this return t; } @@ -737,344 +721,3 @@ bool load_process_module(process_t *p, system_module *m){ p->exposed_fs.close = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.close - (uintptr_t)p->va)); return load_module(&p->exposed_fs); } - -size_t list_processes(void *buf, size_t size, file_offset *offset){ - - if (!buf || !offset || size < sizeof(uint32_t)) return 0; - - fs_dir_list_helper helper = create_dir_list_helper(buf, size); - - process_t *proc = process_list; - if (*offset) { - while (proc && proc->id != *offset) proc = proc->process_next; - } - - while (proc) { - if (proc->id != 0 && proc->state != STOPPED) { - char name[6]; - string_format_buf(name, 6, "%i", proc->id); - - if (!dir_list_fill(&helper, name)){ - if (offset){ - *offset = proc->id; - return dir_buf_size(&helper); - } - } - } - proc = proc->process_next; - } - - return dir_buf_size(&helper); -} - -#define NUM_PROC_FILES 2 - -char* proc_files[NUM_PROC_FILES] = { - "out", - "state" -}; - -size_t list_proc_files(void *buf, size_t size, file_offset *offset){ - - if (!buf || !offset || size < sizeof(uint32_t)) return 0; - - fs_dir_list_helper helper = create_dir_list_helper(buf, size); - - u64 index = offset ? *offset : 0; - - for (int i = index; i < NUM_PROC_FILES; i++){ - kprint(proc_files[i]); - char *name = (char*)((uptr)helper.list + 4 + helper.offset); - if (!dir_list_fill(&helper, proc_files[i])){ - if (offset) *offset = i; - return dir_buf_size(&helper); - } - kprint(name); - } - return dir_buf_size(&helper); -} - -size_t readdir_proc(const char *path, void *buf, size_t size, file_offset *offset){ - irq_flags_t irq = irq_save_disable(); - if (!strlen(path)){ - size_t res = list_processes(buf, size, offset); - irq_restore(irq); - return res; - } - const char *pid_s = seek_to(path, '/'); - path = seek_to(pid_s, '/'); - uint64_t pid = parse_int_u64(pid_s, path - pid_s); - process_t *proc = get_proc_by_pid(pid); - if (!proc) { - irq_restore(irq); - return false; - } - if (!strlen(path)){ - size_t res = list_proc_files(buf, size, offset); - irq_restore(irq); - return res; - } - irq_restore(irq); - return false; -} - -FS_RESULT open_proc(const char *path, file *descriptor){ - uint64_t fid = reserve_fd_gid(path); - irq_flags_t irq = irq_save_disable(); - module_file *mfile = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(uint64_t)); - if (mfile){ - descriptor->id = mfile->fid; - descriptor->size = mfile->file_size; - descriptor->cursor = 0; - mfile->references++; - procfs_owner *owner_info = (procfs_owner*)mfile->private_data; - if (owner_info && owner_info->proc && owner_info->proc->id == owner_info->pid) owner_info->proc->procfs_refs++; - irq_restore(irq); - return FS_RESULT_SUCCESS; - } - const char *pid_s = seek_to(path, '/'); - path = seek_to(pid_s, '/'); - uint64_t pid = parse_int_u64(pid_s, path - pid_s); - process_t *proc = get_proc_by_pid(pid); - if (!proc) { - irq_restore(irq); - return FS_RESULT_NOTFOUND; - } - descriptor->id = fid; - descriptor->cursor = 0; - module_file *file = procfs_alloc(sizeof(module_file)); - if (!file) { - irq_restore(irq); - return FS_RESULT_DRIVER_ERROR; - } - procfs_owner *owner_info = procfs_alloc(sizeof(procfs_owner)); - if (!owner_info) { - irq_restore(irq); - release(file); - return FS_RESULT_DRIVER_ERROR; - } - owner_info->proc = proc; - owner_info->pid = proc->id; - file->fid = fid; - file->private_data = owner_info; - file->references = 1; - if (strcmp_case(path, "out",true) == 0){ - descriptor->size = proc->output ? proc->output_size : proc->postmortem_output_size; - file->read_only = true; - file->buf = (uptr)(proc->output ? proc->output : proc->postmortem_output); - file->file_buffer = (buffer){ - .buffer = (char*)(proc->output ? proc->output : proc->postmortem_output), - .buffer_size = proc->output ? proc->output_size : proc->postmortem_output_size, - .limit = proc->output ? PROC_OUT_BUF : proc->postmortem_output_size, - .options = proc->output ? buffer_circular : buffer_static, - .cursor = proc->output ? proc->output_size : 0, - }; - proc->procfs_refs++; - } else if (strcmp_case(path, "state",true) == 0){ - descriptor->size = sizeof(proc->state); - file->read_only = true; - file->buf = (uptr)&proc->state; - file->file_buffer = (buffer){ - .buffer = (char*)&proc->state, - .limit = sizeof(proc->state), - .options = buffer_static, - .buffer_size = sizeof(proc->state), - .cursor = 0, - }; - proc->procfs_refs++; - } else { - irq_restore(irq); - release((void*)owner_info); - release(file); - return FS_RESULT_NOTFOUND; - } - file->file_size = descriptor->size; - int put = hash_map_put(proc_opened_files, &descriptor->id, sizeof(uint64_t), file); - irq_restore(irq); - if (put >= 0) return FS_RESULT_SUCCESS; - if ((uintptr_t)file->file_buffer.buffer == (uintptr_t)proc->output || (uintptr_t)file->file_buffer.buffer == (uintptr_t)proc->postmortem_output || (uintptr_t)file->file_buffer.buffer == (uintptr_t)&proc->state) { - if (proc->procfs_refs) proc->procfs_refs--; - } - release((void*)owner_info); - release(file); - return FS_RESULT_DRIVER_ERROR; -} - -bool stat_proc(const char *path, fs_stat *out_stat){ - if (!out_stat) return false; - irq_flags_t irq = irq_save_disable(); - if (!strlen(path)){ - bool res = stat_dir(out_stat); - irq_restore(irq); - return res; - } - const char *pid_s = seek_to(path, '/'); - path = seek_to(pid_s, '/'); - uint64_t pid = parse_int_u64(pid_s, path - pid_s); - process_t *proc = get_proc_by_pid(pid); - if (!proc) { - irq_restore(irq); - return false; - } - if (!strlen(path)){ - bool res = stat_dir(out_stat); - irq_restore(irq); - return res; - } - out_stat->type = entry_file; - if (strcmp_case(path, "out",true) == 0){ - out_stat->size = proc->output_size; - out_stat->data_type = DATA_SIG_TEXT; - } - if (strcmp_case(path, "state",true) == 0){ - out_stat->size = sizeof(proc->state); - out_stat->data_type = DATA_SIG_PROC_ST; - } - irq_restore(irq); - return true; -} - -int find_open_proc_file(void *node, void* key){ - uint64_t *fid = (uint64_t*)key; - module_file *file = (module_file*)node; - if (file->fid == *fid) return 0; - return -1; -} - -int find_open_proc_file_buffer(void *node, void* key){ - uintptr_t *buf = (uintptr_t*)key; - module_file *file = (module_file*)node; - if ((uintptr_t)file->file_buffer.buffer == *buf) return 0; - return -1; -} - -size_t read_proc(file* fd, char *buf, size_t size, file_offset offset){ - if (!proc_opened_files){ - kprint("No files open"); - return 0; - } - irq_flags_t irq = irq_save_disable(); - module_file *file = (module_file*)hash_map_get(proc_opened_files, &fd->id, sizeof(uint64_t)); - if (!file) { - irq_restore(irq); - return 0; - } - size_t s = buffer_read(&file->file_buffer, buf, size, offset); - fd->size = file->file_size; - irq_restore(irq); - return s; -} - -size_t write_proc(file* fd, const char *buf, size_t size, file_offset offset){ - process_t *proc = get_current_proc(); - if (fd->id == FD_OUT){ - if (!proc || !size) return 0; - if (!proc->output) { - proc->output = (kaddr_t)palloc(PROC_OUT_BUF, MEM_PRIV_KERNEL, MEM_RW, true); - if (!proc->output) return 0; - } - irq_flags_t irq = irq_save_disable(); - - buffer file_buffer = { - .buffer = (char*)proc->output, - .buffer_size = proc->output_size, - .limit = PROC_OUT_BUF, - .options = buffer_circular, - .cursor = proc->output_size, - }; - - size = min(size, file_buffer.limit); - size_t written = buffer_write_lim(&file_buffer, buf, size); - - proc->output_size = file_buffer.buffer_size; - fd->size = proc->output_size; - - if (proc_opened_files){ - char fullpath[48] = {}; - string_format_buf(fullpath, sizeof(fullpath), "/%i/out", proc->id); - uint64_t fid = reserve_fd_gid(fullpath); - module_file *file = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); - if (file) { - file->buf = (uptr)proc->output; - file->file_buffer.buffer = (char*)proc->output; - file->file_buffer.buffer_size = proc->output_size; - file->file_buffer.limit = PROC_OUT_BUF; - file->file_buffer.cursor = proc->output_size; - file->file_buffer.options = buffer_circular; - file->file_size = proc->output_size; - } - } - - irq_restore(irq); - return written; - } - - if (!proc_opened_files){ - kprint("No files open"); - return 0; - } - irq_flags_t irq = irq_save_disable(); - module_file *file = (module_file*)hash_map_get(proc_opened_files, &fd->id, sizeof(uint64_t)); - bool ro = file && file->read_only; - irq_restore(irq); - if (!file) return 0; - if (ro) return 0; - return 0; -} - -void close_proc(file *fd) { - if (!fd) return; - if (!proc_opened_files) return; - - uint64_t fid = fd->id; - process_t *reset_proc = 0; - irq_flags_t irq = irq_save_disable(); - module_file *mfile = (module_file*)hash_map_get(proc_opened_files, &fid, sizeof(fid)); - if (!mfile) { - irq_restore(irq); - return; - } - - procfs_owner *owner_info = (procfs_owner*)mfile->private_data; - process_t *owner = 0; - if (owner_info && owner_info->proc && owner_info->proc->id == owner_info->pid) owner = owner_info->proc; - if (owner) { - if (owner->procfs_refs) owner->procfs_refs--; - if (process_can_reset(owner) && process_has_runtime_state(owner)) reset_proc = owner; - } - - if (mfile->references > 0) mfile->references--; - if (mfile->references == 0) { - void *owned = mfile->file_buffer.buffer; - buffer_options options = mfile->file_buffer.options; - bool owned_postmortem = owner && owned == (void*)owner->postmortem_output; - hash_map_remove(proc_opened_files, &fid, sizeof(fid), 0); - irq_restore(irq); - if (owned && options == buffer_opt_none && !(reset_proc && owned_postmortem)) { - release(owned); - if (owned_postmortem) { - owner->postmortem_output = 0; - owner->postmortem_output_size = 0; - } - } - if (mfile->private_data) release(mfile->private_data); - release(mfile); - if (reset_proc) reset_process(reset_proc); - return; - } - irq_restore(irq); -} - -system_module scheduler_module = (system_module){ - .name = "scheduler", - .mount = "proc", - .version = VERSION_NUM(0, 1, 0, 1), - .init = init_scheduler_module, - .fini = 0, - .open = open_proc, - .read = read_proc, - .write = write_proc, - .close = close_proc, - .getstat = stat_proc, - .readdir = readdir_proc, -}; diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 5f83f2dc..ef1de961 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -3,6 +3,7 @@ #include "types.h" #include "process/process.h" #include "files/system_module.h" +#include "procfs.h" typedef enum { INTERRUPT, @@ -63,6 +64,6 @@ process_t *get_all_processes(); thread_t new_thread(process_t *proc, uptr entry_point); -extern system_module scheduler_module; +bool init_scheduler(); extern char ksp[]; diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index b5f4cd72..7cf9864f 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -195,7 +195,7 @@ u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ if ((uptr)current_thread == (uptr)ctx) stop_current_process(current_thread->PROC_X0); else - switch_proc(YIELD); + switch_proc(YIELD);//TODO: proper cleanup return 0; } diff --git a/user/demo/default_process.c b/user/demo/default_process.c index 3a439f4e..508e6110 100644 --- a/user/demo/default_process.c +++ b/user/demo/default_process.c @@ -247,6 +247,7 @@ int main(int argc, char* argv[]){ if (index >= 0 && index < count) return demos[index].fn(); } + if (ev.key == KEY_ESC) halt(0); } } } From 904d83f5510d8b632a63ad6b9d18a8f5efbd553f Mon Sep 17 00:00:00 2001 From: di Date: Fri, 26 Jun 2026 00:00:00 +0000 Subject: [PATCH 04/65] [KPROC] proper stack --- kernel/process/scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index ab9e9dc3..0559447d 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -690,7 +690,7 @@ void wake_processes(){ } sizedptr new_stack(process_t *proc){ - uptr stack_limit = (uptr)0x00008FFFFFFFF000ULL; + uptr stack_limit = is_privileged(proc->spsr) ? (uptr)palloc(proc->stack_size, MEM_PRIV_KERNEL, MEM_RW, true) : 0x00008FFFFFFFF000ULL; uptr stack_top = stack_limit - proc->stack_size; mm_add_vma(&proc->mm, proc->mm.stack_top, stack_limit, MEM_RW, VMA_KIND_ANON, VMA_FLAG_DEMAND); print("New stack at %llx-%llx",stack_limit,stack_top); From 100af001dc1f4c6f4823baaea18fd2b7f4aa24cf Mon Sep 17 00:00:00 2001 From: di Date: Fri, 26 Jun 2026 00:00:00 +0000 Subject: [PATCH 05/65] [MEM] stack manager --- kernel/memory/mm_process.c | 16 +++++++++---- kernel/memory/mm_process.h | 3 ++- kernel/process/loading/elf_file.c | 4 ++-- kernel/process/loading/process_loader.c | 21 ++++++++++------ kernel/process/process.h | 4 +++- kernel/process/scheduler.c | 18 ++++---------- kernel/process/stack_manager.c | 24 +++++++++++++++++++ kernel/process/stack_manager.h | 17 +++++++++++++ kernel/process/syscall.c | 18 +++++++------- kernel/process/uaccess.c | 32 ++++++++++++------------- kernel/process/uaccess.h | 12 +++++----- 11 files changed, 109 insertions(+), 60 deletions(-) create mode 100644 kernel/process/stack_manager.c create mode 100644 kernel/process/stack_manager.h diff --git a/kernel/memory/mm_process.c b/kernel/memory/mm_process.c index ce6c0c69..8d27e1a3 100644 --- a/kernel/memory/mm_process.c +++ b/kernel/memory/mm_process.c @@ -3,6 +3,7 @@ #include "memory/addr.h" #include "std/memory.h" #include "memory/mm_process.h" +#include "process/stack_manager.h" vma* mm_find_vma(mm_struct *mm, uaddr_t va){ if (!mm) return 0; @@ -29,7 +30,7 @@ bool mm_add_vma(mm_struct *mm, uaddr_t start, uaddr_t end, uint8_t prot, uint8_t for (uint16_t i = mm->vma_count; i > ins; i--) mm->vmas[i] = mm->vmas[i - 1]; - mm->vmas[ins] = (vma){start, end, prot, kind, flags}; + mm->vmas[ins] = (vma){ start, end, prot, kind, flags }; mm->vma_count++; if (ins > 0) { @@ -160,7 +161,7 @@ uaddr_t mm_alloc_mmap(mm_struct *mm, size_t size, uint8_t prot, uint8_t kind, ui return base; } -bool mm_try_handle_page_fault(process_t *proc, uintptr_t far, uint64_t esr) { +bool mm_try_handle_page_fault(process_t *proc, thread_t *current_thread, uintptr_t far, uint64_t esr) { if (!proc || !proc->mm.ttbr0) return false; uint64_t ec = (esr >> 26) & 0x3F; @@ -189,12 +190,13 @@ bool mm_try_handle_page_fault(process_t *proc, uintptr_t far, uint64_t esr) { if (!(m->flags & VMA_FLAG_DEMAND)) return false; if (m->kind == VMA_KIND_STACK) { - uintptr_t sp = proc->sp & ~(PAGE_SIZE - 1); +#if LEGACY_STACK + uintptr_t sp = current_thread->sp & ~(PAGE_SIZE - 1); uintptr_t low = sp > (32 * PAGE_SIZE) ? sp - (32 * PAGE_SIZE) : proc->mm.stack_limit; - if (va_page < low || va_page < proc->mm.stack_limit || va_page >= proc->mm.stack_top) return false; + if (va_page < low || va_page < stack_min_addr || va_page >= stack_max_addr){ print("Out of bounds %llx < %llx | %llx < %llx | %llx >= %llx",va_page,low,va_page,proc->mm.stack_limit,va_page,proc->mm.stack_top); return false; } uintptr_t grow_to = proc->mm.stack_commit; if (va_page < grow_to) grow_to = va_page; - if (((proc->mm.stack_top - grow_to) / PAGE_SIZE) > proc->mm.cap_stack_pages) return false; + if (((proc->mm.stack_top - grow_to) / PAGE_SIZE) > proc->mm.cap_stack_pages){ print("Too many pages"); return false; } for (uintptr_t page = proc->mm.stack_commit - PAGE_SIZE; page >= grow_to; page -= PAGE_SIZE) { paddr_t phys = palloc_inner(PAGE_SIZE, MEM_PRIV_USER, MEM_RW, true, false); if (!phys) { @@ -212,6 +214,10 @@ bool mm_try_handle_page_fault(process_t *proc, uintptr_t far, uint64_t esr) { if (page == 0) break; } proc->mm.stack_commit = grow_to; +#else + paddr_t phys = palloc_inner(PAGE_SIZE, MEM_PRIV_USER, MEM_RW, true, false); + mmu_map_4kb((uint64_t*)proc->mm.ttbr0, va_page, phys, MAIR_IDX_NORMAL, m->prot | MEM_NORM, MEM_PRIV_USER); +#endif mmu_flush_asid(proc->mm.asid); return true; } diff --git a/kernel/memory/mm_process.h b/kernel/memory/mm_process.h index 6a6f3d2b..6454abaa 100644 --- a/kernel/memory/mm_process.h +++ b/kernel/memory/mm_process.h @@ -4,6 +4,7 @@ #include "memory/page_allocator.h" typedef struct process process_t; +typedef struct thread thread_t; #define VMA_FLAG_DEMAND 1 #define VMA_FLAG_USERALLOC 2 @@ -55,4 +56,4 @@ vma* mm_find_vma(mm_struct *mm, uaddr_t va); bool mm_add_vma(mm_struct *mm, uaddr_t start, uaddr_t end, uint8_t prot, uint8_t kind, uint8_t flags); bool mm_remove_vma(mm_struct *mm, uaddr_t start, uaddr_t end); uaddr_t mm_alloc_mmap(mm_struct *mm, size_t size, uint8_t prot, uint8_t kind, uint8_t flags); -bool mm_try_handle_page_fault(process_t *proc, uintptr_t far, uint64_t esr); \ No newline at end of file +bool mm_try_handle_page_fault(process_t *proc, thread_t *current_thread, uintptr_t far, uint64_t esr); \ No newline at end of file diff --git a/kernel/process/loading/elf_file.c b/kernel/process/loading/elf_file.c index d7f0804e..5b3c39f9 100644 --- a/kernel/process/loading/elf_file.c +++ b/kernel/process/loading/elf_file.c @@ -163,13 +163,13 @@ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { size_t off = 0; for (int i = 0; i < argc; i++) { size_t len = strlen(argv[i]) + 1; - if (copy_to_user(proc, str_base + off, argv[i], len) != UACCESS_OK) return false; + if (copy_to_user(proc, (thread_t*)proc, str_base + off, argv[i], len) != UACCESS_OK) return false; arg_ptrs[i] = str_base + off; off += len; } arg_ptrs[argc] = 0; - if (copy_to_user(proc, sp, arg_ptrs, argv_size) != UACCESS_OK) return false; + if (copy_to_user(proc, (thread_t*)proc, sp, arg_ptrs, argv_size) != UACCESS_OK) return false; return true; } diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index a8e09cca..a6ef7c80 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -12,6 +12,7 @@ #include "string/string.h" #include "syscalls/syscall_codes.h" #include "process/isolated_fs/isolated_fs.h" +#include "process/stack_manager.h" typedef struct { uint64_t code_base_start; @@ -366,11 +367,19 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->code = dest; proc->code_size = code_size; - uint64_t stack_max_size = 0x800000; //TODO it shouldnt be fix + proc->spsr = 0; + uint64_t shared_pages = 1; size_t shared_size = shared_pages * PAGE_SIZE; - uaddr_t stack_top = 0x00007FFFFFFFF000ULL; - uaddr_t stack_limit = stack_top - stack_max_size; + + stack_t main_stack = new_stack(proc); + if (!main_stack.top || !main_stack.size){ + reset_process(proc); + return 0; + } + + uaddr_t stack_top = main_stack.top; + uaddr_t stack_limit = stack_top - main_stack.max; uaddr_t stack_commit = stack_top; uaddr_t mmap_top = stack_limit - PAGE_SIZE; uaddr_t shared_base = mmap_top - (shared_size - PAGE_SIZE); @@ -392,17 +401,16 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat uint64_t total_pages = get_total_user_ram() / PAGE_SIZE; if (!total_pages) total_pages = 1; - proc->mm.cap_stack_pages = stack_max_size / PAGE_SIZE; + proc->mm.cap_stack_pages = (stack_max_addr-stack_min_addr) / PAGE_SIZE; proc->mm.cap_anon_pages = total_pages / 2; if (proc->mm.cap_anon_pages < 128) proc->mm.cap_anon_pages = 128; for (uint64_t i = 0; i < shared_pages; i++) mmu_map_4kb((uint64_t*)ttbr, (uint64_t)(shared_base + (i * PAGE_SIZE)), (paddr_t)(shared_page + (i * PAGE_SIZE)), MAIR_IDX_NORMAL, MEM_EXEC | MEM_NORM, MEM_PRIV_SHARED); mm_add_vma(&proc->mm, shared_base, shared_base + shared_size, MEM_EXEC | MEM_NORM, VMA_KIND_SPECIAL, VMA_FLAG_NOFREE); - mm_add_vma(&proc->mm, proc->mm.stack_limit, proc->mm.stack_top, MEM_RW, VMA_KIND_STACK, VMA_FLAG_DEMAND); proc->stack = stack_top; proc->stack_phys = 0; - proc->stack_size = stack_max_size; + proc->stack_size = main_stack.size; proc->mm.rss_stack_pages = 0; proc->sp = proc->stack; @@ -411,7 +419,6 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->regs[30] = shared_base; proc->shared_page = shared_base; kprintf("User process %s (%i) allocated at %llx entry=%llx stack=%llx-%llx (phys=%llx-%llx) anon=%llx (phys=%llx)", name, proc->id, proc, (uint64_t)proc->pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->stack_phys, (uint64_t)proc->stack_phys, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); - proc->spsr = 0; proc->state = BLOCKED; make_process_fs(proc,proc->bundle); diff --git a/kernel/process/process.h b/kernel/process/process.h index 88f0fcb5..0ef17c76 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -57,7 +57,7 @@ typedef struct { typedef enum { STOPPED, READY, RUNNING, BLOCKED } process_state; -typedef struct { +typedef struct thread { uint64_t regs[31]; // x0–x30 uintptr_t sp; uintptr_t pc; @@ -125,6 +125,8 @@ typedef struct process { struct process *process_next; } process_t; +#define is_privileged(spsr) (spsr & 0xf) + //Helper functions for accessing registers mapped to scratch regs #define PROC_X0 regs[0] #define PROC_X1 regs[1] diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 0559447d..cb64c207 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -20,6 +20,7 @@ #include "string/string.h" #include "alloc/allocate.h" #include "files/dir_list.h" +#include "stack_manager.h" extern void save_pc_interrupt(uintptr_t ptr); extern void restore_context(uintptr_t ptr); @@ -31,8 +32,6 @@ process_t *process_list = 0; uint16_t proc_count = 0; uint16_t next_proc_index = 1; -#define is_privileged(spsr) (spsr & 0xf) - //TODO maybe use a weighted ready queue based on process priority CQueue ready_queue = {}; linked_list_t sleeping_list = {}; @@ -689,25 +688,18 @@ void wake_processes(){ irq_restore(irq); } -sizedptr new_stack(process_t *proc){ - uptr stack_limit = is_privileged(proc->spsr) ? (uptr)palloc(proc->stack_size, MEM_PRIV_KERNEL, MEM_RW, true) : 0x00008FFFFFFFF000ULL; - uptr stack_top = stack_limit - proc->stack_size; - mm_add_vma(&proc->mm, proc->mm.stack_top, stack_limit, MEM_RW, VMA_KIND_ANON, VMA_FLAG_DEMAND); - print("New stack at %llx-%llx",stack_limit,stack_top); - return (sizedptr){.ptr = stack_top, proc->stack_size}; -} - thread_t new_thread(process_t *proc, uptr entry_point){ - sizedptr stack = new_stack(proc); + stack_t stack = new_stack(proc); + if (!stack.top || !stack.size) return (thread_t){}; thread_t t = { .pc = entry_point, .pid = proc->id, .regs = {}, - .sp = stack.ptr, + .sp = stack.top, .stack_size = stack.size, .spsr = proc->spsr }; - t.regs[30] = is_privileged(proc->spsr) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32);//TODO: kernel processes don't have this + t.regs[30] = is_privileged(proc->spsr) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32); return t; } diff --git a/kernel/process/stack_manager.c b/kernel/process/stack_manager.c new file mode 100644 index 00000000..9140721f --- /dev/null +++ b/kernel/process/stack_manager.c @@ -0,0 +1,24 @@ +#include "stack_manager.h" +#include "exceptions/exception_handler.h" + +uptr next_stack_addr(process_t *proc){ + if (is_privileged(proc->spsr)) return 0; + for (uptr start = stack_max_addr; start > stack_min_addr; start -= 0x100000000000){ + vma *m = mm_find_vma(&proc->mm, start-stack_max); + if (!m){ + return start; + } + } + print("Damn girl how many stacks u got"); + return 0; +} + +stack_t new_stack(process_t *proc){ + uptr stack_top = is_privileged(proc->spsr) ? (uptr)palloc(stack_max, MEM_PRIV_KERNEL, MEM_RW, true) : next_stack_addr(proc); + if (!stack_top) return (stack_t){}; + uptr stack_limit = stack_top - stack_max; + print("New stack at %llx-%llx",stack_limit,stack_top); + if (!mm_add_vma(&proc->mm, stack_limit, stack_top, MEM_RW, VMA_KIND_STACK, VMA_FLAG_DEMAND)) + return (stack_t){}; + return (stack_t){.top = stack_top, .size = stack_max, .max = stack_max}; +} \ No newline at end of file diff --git a/kernel/process/stack_manager.h b/kernel/process/stack_manager.h new file mode 100644 index 00000000..b2a7b876 --- /dev/null +++ b/kernel/process/stack_manager.h @@ -0,0 +1,17 @@ +#pragma once + +#include "types.h" +#include "process.h" + +#define stack_max 0x100000 +#define stack_max_addr 0x7ffffffff000 +#define stack_distance (stack_max + PAGE_SIZE) +#define stack_min_addr 0x100000000000ULL + +typedef struct { + uptr top; + size_t max; + size_t size; +} stack_t; + +stack_t new_stack(process_t *proc); \ No newline at end of file diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 7cf9864f..d190961e 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -41,17 +41,17 @@ uintptr_t cpec; #define SYSCALL_STR(name, arg, write)\ char *name = (char*)current_thread->arg;\ if (!name) return 0;\ - if (!validate_address(ctx, (uptr)name, sizeof(name), write)) return 0; + if (!validate_address(ctx, current_thread, (uptr)name, sizeof(name), write)) return 0; #define SYSCALL_ARG(type, name, arg, write) \ type *name = (type*)current_thread->arg;\ if (!name) return 0;\ - if (!validate_address(ctx, (uptr)name, sizeof(type), write)) return 0;\ + if (!validate_address(ctx, current_thread, (uptr)name, sizeof(type), write)) return 0;\ #define SYSCALL_ARG_SIZE(type, name, size, arg, write) \ type *name = (type*)current_thread->arg;\ if (!name && size) return 0;\ - if (!validate_address(ctx, (uptr)name, size, write)) return 0;\ + if (!validate_address(ctx, current_thread, (uptr)name, size, write)) return 0;\ //TEST: What happens if we pass another process' data in here? typedef uint64_t (*syscall_entry)(process_t *ctx, thread_t *current_thread); @@ -210,7 +210,7 @@ u64 syscall_exec(process_t *ctx, thread_t *current_thread){ user_argv_t user_argv = {}; - uaccess_result_t ur = copy_argv_from_user(ctx, argc, uargv, &user_argv); + uaccess_result_t ur = copy_argv_from_user(ctx, current_thread, argc, uargv, &user_argv); if (ur != UACCESS_OK) return 0; process_t *p = execute(prog_name, argc, user_argv.argv, mode); @@ -468,9 +468,9 @@ u64 syscall_signal_send(process_t* ctx, thread_t *current_thread){ u64 syscall_signal_handler(process_t* ctx, thread_t *current_thread){ signal_types type = current_thread->PROC_X0; uptr handler = current_thread->PROC_X1; - print("Handler is %x",handler); + if (!handler) return 0; - if (!validate_address(ctx, handler, sizeof(uptr), false)) return 0; + if (!validate_address(ctx, current_thread, handler, sizeof(uptr), false)) return 0; return register_signal_handler(ctx, type, (signal_handler)handler); } @@ -634,6 +634,7 @@ void sync_el0_handler_c(){ #endif process_t *proc = get_current_proc(); + thread_t *current_thread = (thread_t*)cpec; uint64_t elr; asm volatile ("mrs %0, elr_el1" : "=r"(elr)); @@ -651,7 +652,7 @@ void sync_el0_handler_c(){ uint64_t far; asm volatile ("mrs %0, far_el1" : "=r"(far)); if (ec == 0x24 || ec == 0x20){ - if (mm_try_handle_page_fault(proc, far, esr)){ + if (mm_try_handle_page_fault(proc, current_thread, far, esr)){ syscall_depth--; process_restore(); } @@ -661,7 +662,6 @@ void sync_el0_handler_c(){ if (ec == 0x15) { syscall_entry entry = syscalls[iss]; if (entry){ - thread_t *current_thread = (thread_t*)cpec; result = entry(proc, current_thread); } else { kprintf("Unknown syscall in process. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); @@ -680,7 +680,7 @@ void sync_el0_handler_c(){ handle_exception("UNEXPECTED EXCEPTION", ec); while (true); } else { - kprintf("Process has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", esr, elr, far, proc->sp); + kprintf("Process has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", esr, elr, far, current_thread->sp); if (syscall_depth <= 2) coredump(esr, elr, far, proc->sp); syscall_depth--; stop_current_process(ec); diff --git a/kernel/process/uaccess.c b/kernel/process/uaccess.c index 6705f0e9..726dfd5c 100644 --- a/kernel/process/uaccess.c +++ b/kernel/process/uaccess.c @@ -5,7 +5,7 @@ #include "std/memory.h" #include "alloc/allocate.h" -bool access_ok_range(process_t *proc, uintptr_t addr, size_t size, bool want_write) { +bool access_ok_range(process_t *proc, thread_t *current_thread, uintptr_t addr, size_t size, bool want_write) { if (!proc) return false; if (!proc->mm.ttbr0) return false; if (!size) return true; @@ -30,10 +30,10 @@ bool access_ok_range(process_t *proc, uintptr_t addr, size_t size, bool want_wri return true; } -uaccess_result_t copy_from_user(process_t *proc, void *dst, uintptr_t src, size_t size) { +uaccess_result_t copy_from_user(process_t *proc, thread_t *current_thread, void *dst, uintptr_t src, size_t size) { if (!dst && size) return UACCESS_EINVAL; if (!size) return UACCESS_OK; - if (!access_ok_range(proc, src, size, false)) return UACCESS_EFAULT; + if (!access_ok_range(proc, current_thread, src, size, false)) return UACCESS_EFAULT; uint8_t *d = (uint8_t*)dst; @@ -46,7 +46,7 @@ uaccess_result_t copy_from_user(process_t *proc, void *dst, uintptr_t src, size_ uintptr_t pa =mmu_translate((uint64_t*)proc->mm.ttbr0, src, &st); if (st) { uint64_t esr = (0x24ULL << 26) | 0x7ULL; - if (!mm_try_handle_page_fault(proc, src, esr)) return UACCESS_EFAULT; + if (!mm_try_handle_page_fault(proc, current_thread, src, esr)) return UACCESS_EFAULT; pa = mmu_translate((uint64_t*)proc->mm.ttbr0, src, &st); if (st) return UACCESS_EFAULT; @@ -61,10 +61,10 @@ uaccess_result_t copy_from_user(process_t *proc, void *dst, uintptr_t src, size_ return UACCESS_OK; } -bool validate_address(process_t *proc, uintptr_t addr, size_t size, bool want_write) { +bool validate_address(process_t *proc, thread_t *current_thread, uintptr_t addr, size_t size, bool want_write) { if (!addr && size) return false; if (!size) return true; - if (!access_ok_range(proc, addr, size, want_write)) return false; + if (!access_ok_range(proc, current_thread, addr, size, want_write)) return false; while (size) { size_t off = addr & (PAGE_SIZE - 1); @@ -75,7 +75,7 @@ bool validate_address(process_t *proc, uintptr_t addr, size_t size, bool want_wr mmu_translate((uint64_t*)proc->mm.ttbr0, addr, &st); if (st) { uint64_t esr = (0x24ULL << 26) | 0x7ULL | (want_write << 6); - if (!mm_try_handle_page_fault(proc, addr, esr)) return false; + if (!mm_try_handle_page_fault(proc, current_thread, addr, esr)) return false; mmu_translate((uint64_t*)proc->mm.ttbr0, addr, &st); if (st) return false; @@ -88,10 +88,10 @@ bool validate_address(process_t *proc, uintptr_t addr, size_t size, bool want_wr return true; } -uaccess_result_t copy_to_user(process_t *proc, uintptr_t dst, const void *src, size_t size) { +uaccess_result_t copy_to_user(process_t *proc, thread_t *current_thread, uintptr_t dst, const void *src, size_t size) { if (!src && size) return UACCESS_EINVAL; if (!size) return UACCESS_OK; - if (!access_ok_range(proc, dst, size, true)) return UACCESS_EFAULT; + if (!access_ok_range(proc, current_thread, dst, size, true)) return UACCESS_EFAULT; const uint8_t *s = (const uint8_t*)src; @@ -104,7 +104,7 @@ uaccess_result_t copy_to_user(process_t *proc, uintptr_t dst, const void *src, s uintptr_t pa = mmu_translate((uint64_t*)proc->mm.ttbr0, dst, &st); if (st) { uint64_t esr = (0x24ULL << 26) | 0x7ULL | (1 << 6); - if (!mm_try_handle_page_fault(proc, dst, esr)) return UACCESS_EFAULT; + if (!mm_try_handle_page_fault(proc, current_thread, dst, esr)) return UACCESS_EFAULT; pa = mmu_translate((uint64_t*)proc->mm.ttbr0, dst, &st); if (st) return UACCESS_EFAULT; @@ -119,7 +119,7 @@ uaccess_result_t copy_to_user(process_t *proc, uintptr_t dst, const void *src, s return UACCESS_OK; } -uaccess_result_t copy_str_from_user(process_t *proc, char *dst, size_t dst_size, uintptr_t src, size_t *out_copied, bool *out_terminated) { +uaccess_result_t copy_str_from_user(process_t *proc, thread_t *current_thread, char *dst, size_t dst_size, uintptr_t src, size_t *out_copied, bool *out_terminated) { if (out_copied) *out_copied = 0; if (out_terminated) *out_terminated = false; if (!dst || !dst_size) return UACCESS_EINVAL; @@ -131,12 +131,12 @@ uaccess_result_t copy_str_from_user(process_t *proc, char *dst, size_t dst_size, while (pos + 1 < dst_size) { size_t chunk = PAGE_SIZE - ((src + pos) & (PAGE_SIZE - 1)); if (chunk > dst_size - 1 - pos) chunk = dst_size - 1 - pos; - if (!access_ok_range(proc, src + pos, chunk, false)) return UACCESS_EFAULT; + if (!access_ok_range(proc, current_thread, src + pos, chunk, false)) return UACCESS_EFAULT; int st = 0; uintptr_t pa = mmu_translate((uint64_t*)proc->mm.ttbr0, src + pos, &st); if (st) { - if (!mm_try_handle_page_fault(proc, src + pos, (0x24ULL << 26) | 0x7ULL)) return UACCESS_EFAULT; + if (!mm_try_handle_page_fault(proc, current_thread, src + pos, (0x24ULL << 26) | 0x7ULL)) return UACCESS_EFAULT; pa = mmu_translate((uint64_t*)proc->mm.ttbr0, src + pos, &st); if (st) return UACCESS_EFAULT; } @@ -156,7 +156,7 @@ uaccess_result_t copy_str_from_user(process_t *proc, char *dst, size_t dst_size, return UACCESS_ENAMETOOLONG; } -uaccess_result_t copy_argv_from_user(process_t *proc, int argc, uintptr_t uargv, user_argv_t *out) { +uaccess_result_t copy_argv_from_user(process_t *proc, thread_t *current_thread, int argc, uintptr_t uargv, user_argv_t *out) { if (!out) return UACCESS_EINVAL; if (argc < 0 || argc > UACCESS_MAX_ARGV) return UACCESS_EINVAL; @@ -165,7 +165,7 @@ uaccess_result_t copy_argv_from_user(process_t *proc, int argc, uintptr_t uargv, for (int i = 0; i < argc; i++) { uintptr_t up = 0; - uaccess_result_t ur = copy_from_user(proc, &up, uargv + ((uintptr_t)i * sizeof(uintptr_t)), sizeof(up)); + uaccess_result_t ur = copy_from_user(proc, current_thread, &up, uargv + ((uintptr_t)i * sizeof(uintptr_t)), sizeof(up)); if (ur != UACCESS_OK) { free_argv_from_user(out); return ur; @@ -178,7 +178,7 @@ uaccess_result_t copy_argv_from_user(process_t *proc, int argc, uintptr_t uargv, char tmp[256] = {}; size_t copied = 0; bool term = false; - ur = copy_str_from_user(proc, tmp, sizeof(tmp), up, &copied, &term); + ur = copy_str_from_user(proc, current_thread, tmp, sizeof(tmp), up, &copied, &term); if (ur != UACCESS_OK) { free_argv_from_user(out); return ur; diff --git a/kernel/process/uaccess.h b/kernel/process/uaccess.h index 598d6a8e..0b2c6090 100644 --- a/kernel/process/uaccess.h +++ b/kernel/process/uaccess.h @@ -21,10 +21,10 @@ typedef struct user_argv { uint64_t bufsz[UACCESS_MAX_ARGV]; } user_argv_t; -bool access_ok_range(process_t *proc, uintptr_t addr, size_t size, bool want_write); -bool validate_address(process_t *proc, uintptr_t addr, size_t size, bool want_write); -uaccess_result_t copy_from_user(process_t *proc, void *dst, uintptr_t src, size_t size); -uaccess_result_t copy_to_user(process_t *proc, uintptr_t dst, const void *src, size_t size); -uaccess_result_t copy_str_from_user(process_t *proc, char *dst, size_t dst_size, uintptr_t src, size_t *out_copied, bool *out_terminated); -uaccess_result_t copy_argv_from_user(process_t *proc, int argc, uintptr_t uargv, user_argv_t *out); +bool access_ok_range(process_t *proc, thread_t *current_thread, uintptr_t addr, size_t size, bool want_write); +bool validate_address(process_t *proc, thread_t *current_thread, uintptr_t addr, size_t size, bool want_write); +uaccess_result_t copy_from_user(process_t *proc, thread_t *current_thread, void *dst, uintptr_t src, size_t size); +uaccess_result_t copy_to_user(process_t *proc, thread_t *current_thread, uintptr_t dst, const void *src, size_t size); +uaccess_result_t copy_str_from_user(process_t *proc, thread_t *current_thread, char *dst, size_t dst_size, uintptr_t src, size_t *out_copied, bool *out_terminated); +uaccess_result_t copy_argv_from_user(process_t *proc, thread_t *current_thread, int argc, uintptr_t uargv, user_argv_t *out); void free_argv_from_user(user_argv_t *argv); From 46f918a8b55c23bb8990b53a9c69faf1d75086b0 Mon Sep 17 00:00:00 2001 From: di Date: Sat, 27 Jun 2026 00:00:00 +0000 Subject: [PATCH 06/65] [FS,WIP] filesystem in userspace skeleton --- kernel/filesystem/fat32.cpp | 1 + kernel/filesystem/filesystem.c | 48 +++++++++++++++++---- kernel/filesystem/modules/module_loader.c | 16 ++++++- kernel/filesystem/virtio_9p_pci.cpp | 1 + kernel/networking/network.cpp | 1 + kernel/process/loading/process_loader.c | 2 +- kernel/process/process.h | 2 + kernel/process/scheduler.c | 52 +++++++++++++---------- kernel/process/scheduler.h | 2 + kernel/process/signals/signals.c | 17 ++------ kernel/process/stack_manager.h | 2 +- kernel/process/syscall.c | 26 +++++++----- kernel/utils/termhistory/termhistory.c | 14 ------ kernel/utils/utils.h | 1 - modules/audio/virt/audio.cpp | 1 + modules/graph/raspi/graphics.cpp | 6 ++- modules/graph/virt/graphics.cpp | 1 + modules/usb/common/usb_common.cpp | 1 + shared | 2 +- user/demo/default_process.c | 3 +- user/terminal/main.c | 25 +++++++++++ 21 files changed, 148 insertions(+), 76 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 70ad4d6b..34fd96ec 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -692,6 +692,7 @@ system_module boot_fs_module = (system_module){ .name = "boot", .mount = "boot", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = boot_partition_init, .fini = boot_partition_fini, .open = boot_partition_open, diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index f8e4157c..fea6e2fb 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -53,7 +53,13 @@ FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor system_module *module = get_module_from(root, &search_path); if (!module) return FS_RESULT_NOTFOUND; if (!module->open) return FS_RESULT_NOTFOUND; - FS_RESULT result = module->open(search_path, descriptor); + FS_RESULT result = FS_RESULT_DRIVER_ERROR; + if (module->owner != get_kernel_proc()->id){ + kprintf("cba rn"); + return result; + } else { + result = module->open(search_path, descriptor); + } if (result != FS_RESULT_SUCCESS) return result; if (!open_files) return FS_RESULT_DRIVER_ERROR; descriptor->cursor = 0; @@ -111,7 +117,13 @@ size_t read_file(file *descriptor, char* buf, size_t size){ .cursor = start_cursor, .data_type = descriptor->data_type }; - size_t amount_read = local.mod->read(&gfd, buf, size, start_cursor); + size_t amount_read = 0; + if (local.mod->owner != get_kernel_proc()->id){ + kprintf("cba rn"); + return amount_read; + } else { + amount_read = local.mod->read(&gfd, buf, size, start_cursor); + } descriptor->cursor = gfd.cursor != start_cursor ? gfd.cursor : start_cursor + amount_read; descriptor->size = gfd.size; return amount_read; @@ -136,7 +148,10 @@ void close_file(file *descriptor){ void close_file_global(file *descriptor, system_module *mod){ if (!mod || !mod->close) return; - mod->close(descriptor); + if (mod->owner != get_kernel_proc()->id) + kprintf("cba rn"); + else + mod->close(descriptor); } size_t write_file(file *descriptor, const char* buf, size_t size){ @@ -162,7 +177,13 @@ size_t write_file(file *descriptor, const char* buf, size_t size){ .cursor = start_cursor, .data_type = descriptor->data_type }; - size_t amount_written = local.mod->write(&gfd, buf, size, 0); + size_t amount_written = 0; + if (local.mod->owner != get_kernel_proc()->id){ + kprintf("cba rn"); + return amount_written; + } else { + amount_written = local.mod->write(&gfd, buf, size, 0); + } descriptor->cursor = gfd.cursor != start_cursor ? gfd.cursor : start_cursor + amount_written; descriptor->size = gfd.size; irq = irq_save_disable(); @@ -217,7 +238,11 @@ size_t list_directory_contents(module_root *root, const char *path, void* buf, s return 0; } if (!mod->readdir) return 0; - return mod->readdir(search_path, buf, size, offset); + if (mod->owner != get_kernel_proc()->id){ + kprintf("cba rn"); + return 0; + } else + return mod->readdir(search_path, buf, size, offset); } bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ @@ -233,7 +258,11 @@ bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ return false; } if (!mod->getstat) return false; - return mod->getstat(search_path, out_stat); + if (mod->owner != get_kernel_proc()->id){ + kprintf("cba rn"); + return false; + } else + return mod->getstat(search_path, out_stat); } bool truncate(file *descriptor, size_t size){ @@ -255,8 +284,11 @@ bool truncate(file *descriptor, size_t size){ .cursor = descriptor->cursor, .data_type = descriptor->data_type }; - - if (!local.mod->truncate(&gfd, size)) return false; + + if (local.mod->owner != get_kernel_proc()->id){ + kprintf("cba rn"); + return false; + } else if (!local.mod->truncate(&gfd, size)) return false; descriptor->size = gfd.size; descriptor->cursor = gfd.cursor; diff --git a/kernel/filesystem/modules/module_loader.c b/kernel/filesystem/modules/module_loader.c index f3b112e8..5565cd53 100644 --- a/kernel/filesystem/modules/module_loader.c +++ b/kernel/filesystem/modules/module_loader.c @@ -7,6 +7,7 @@ #include "files/dir_list.h" #include "exceptions/exception_handler.h" #include "files/vfs.h" +#include "process/scheduler.h" #define MODULE_STRICT @@ -40,6 +41,14 @@ bool load_module_to(hash_map_t* modules, system_module *module){ string_free(format); return false; } + if (!module->owner) module->owner = get_kernel_proc()->id; + if (module->owner != get_kernel_proc()->id){ + process_t *p = get_proc_by_pid(module->owner); + if (!p) return false; + p->fs_thread = new_thread(p, (uptr)module->init); + run_thread_oneshot(&p->fs_thread,p); + //TODO: The thread returns asyncronously, we'll need to handle that + } if (!module->init(module)){ if (strcmp(module->mount,"/console")) kprintf("[MODULE] failed to load module %s. Init failed",module->name); return false; @@ -51,7 +60,12 @@ bool load_module_to(hash_map_t* modules, system_module *module){ bool unload_module_from(hash_map_t* modules, system_module *module){ if (!modules) return false; if (!module->init) return false; - if (module->fini) module->fini(); + if (module->fini) { + if (module->owner != get_kernel_proc()->id){ + kprint("Can't deinit module yet"); + } else + module->fini(); + } hash_map_remove(modules, module->mount, strlen(module->mount), 0); return false; } diff --git a/kernel/filesystem/virtio_9p_pci.cpp b/kernel/filesystem/virtio_9p_pci.cpp index fb266dd7..16e84da9 100644 --- a/kernel/filesystem/virtio_9p_pci.cpp +++ b/kernel/filesystem/virtio_9p_pci.cpp @@ -596,6 +596,7 @@ system_module p9_fs_module = (system_module){ .name = "9PFS", .mount = "home", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = shared_init, .fini = shared_fini, .open = shared_open, diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index 3eb455fb..c1b7e87e 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -90,6 +90,7 @@ system_module net_module = (system_module){ .name = "net", .mount = "net", .version = VERSION_NUM(0, 1, 0, 1), + .owner = 0, .init = network_init, .fini = 0, .open = 0, diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index a6ef7c80..ca6b9ce9 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -381,7 +381,7 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat uaddr_t stack_top = main_stack.top; uaddr_t stack_limit = stack_top - main_stack.max; uaddr_t stack_commit = stack_top; - uaddr_t mmap_top = stack_limit - PAGE_SIZE; + uaddr_t mmap_top = stack_min_addr - PAGE_SIZE; uaddr_t shared_base = mmap_top - (shared_size - PAGE_SIZE); uaddr_t mmap_bottom = (max_map + (PAGE_SIZE*4) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); diff --git a/kernel/process/process.h b/kernel/process/process.h index 0ef17c76..7834317c 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -80,6 +80,7 @@ typedef struct process { paddr_t stack_phys; uint64_t stack_size; //Thread ends + thread_t *pending_thread; uint16_t id; bool in_ready_queue; bool sleeping; @@ -118,6 +119,7 @@ typedef struct process { sizedptr debug_lines; sizedptr debug_line_str; system_module exposed_fs; + thread_t fs_thread; mm_struct mm; int thread_count; environment_data environment; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index cb64c207..83653ca0 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -174,22 +174,15 @@ void process_restore(){ if (!current_proc->mm.ttbr0) panic("process_restore user process without ttbr0", cpec); if (current_proc->pc >= HIGH_VA) panic("user pc in kernel VA", current_proc->pc); mmu_ttbr0_enable_user(); - } else mmu_ttbr0_disable_user(); - if (current_proc->signal_buffer.read_index != current_proc->signal_buffer.write_index){ - signal_info_t *info = ¤t_proc->signal_buffer.entries[current_proc->signal_buffer.read_index];//TODO: Wrong, this should be copied into userland mem - current_proc->signal_buffer.read_index = (current_proc->signal_buffer.read_index + 1) % INPUT_BUFFER_CAPACITY; - if (can_signal_be_handled(info->type)){ - thread_t *handler = ¤t_proc->signal_handlers[info->type]; - if (handler->pc){ - handler->spsr = current_proc->spsr; - cpec = (uptr)handler; - restore_context(cpec); - } - else handle_signal_default(current_proc, info); - } else handle_signal_default(current_proc, info); - switch_proc(RECV_SIGNAL);//TODO: wasteful, we might have a lot of CPU time left for this proc to use - } else - restore_context(cpec); + } else mmu_ttbr0_disable_user(); + if (current_proc->pending_thread){ + if (current_proc->pending_thread->thread_state != STOPPED){ + cpec = (uptr)current_proc->pending_thread; + } else { + current_proc->pending_thread = 0; + } + } + restore_context(cpec); } bool start_scheduler(){ @@ -697,19 +690,34 @@ thread_t new_thread(process_t *proc, uptr entry_point){ .regs = {}, .sp = stack.top, .stack_size = stack.size, + .stack = stack.top, .spsr = proc->spsr }; t.regs[30] = is_privileged(proc->spsr) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32); return t; } +u64 run_thread_oneshot(thread_t *t, process_t *p){ + process_t *cproc = current_proc; + if (p != cproc){ + if (p->mm.ttbr0) mmu_asid_ensure(&p->mm); + mmu_swap_ttbr(p->mm.ttbr0 ? &p->mm : 0); + mmu_ttbr0_enable_user(); + } + t->sp = t->stack-sizeof(system_module);//TODO: stack needs not be reset past args + t->spsr = p->spsr; + t->thread_state = RUNNING; + cpec = (uptr)t; + kprintf("STACK %llx and shared on %llx. Running %llx, after which %llx",t->sp,p->shared_page,t->pc,t->regs[30]); + timer_reset(p->priority); + p->pending_thread = t; + restore_context(cpec); + panic("Somehow the thread has returned",(uptr)t); + return 0; +} + bool load_process_module(process_t *p, system_module *m){ p->exposed_fs = *m; - p->exposed_fs.init = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.init - (uintptr_t)p->va)); - p->exposed_fs.fini = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.fini - (uintptr_t)p->va)); - p->exposed_fs.open = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.open - (uintptr_t)p->va)); - p->exposed_fs.read = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.read - (uintptr_t)p->va)); - p->exposed_fs.write = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.write - (uintptr_t)p->va)); - p->exposed_fs.close = PHYS_TO_VIRT_P(p->code + ((uintptr_t)p->exposed_fs.close - (uintptr_t)p->va)); + p->exposed_fs.owner = p->id; return load_module(&p->exposed_fs); } diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index ef1de961..276d425c 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -66,4 +66,6 @@ thread_t new_thread(process_t *proc, uptr entry_point); bool init_scheduler(); +u64 run_thread_oneshot(thread_t *t, process_t *p); + extern char ksp[]; diff --git a/kernel/process/signals/signals.c b/kernel/process/signals/signals.c index 02aa4d2d..b5887e3d 100644 --- a/kernel/process/signals/signals.c +++ b/kernel/process/signals/signals.c @@ -30,19 +30,10 @@ bool send_signal_proc_proc(signal_types type, i64 value, process_t *source, proc return true; } - signal_buffer_t *buffer = &destination->signal_buffer; - - uint32_t next_index = (buffer->write_index + 1) % INPUT_BUFFER_CAPACITY; - - buffer->entries[buffer->write_index] = (signal_info_t){ - .sender = source->id, - .type = type, - .value = value, - }; - buffer->write_index = next_index; - - if (buffer->write_index == buffer->read_index) - buffer->read_index = (buffer->read_index + 1) % INPUT_BUFFER_CAPACITY; + thread_t *t = zalloc(sizeof(thread_t)); + *t = new_thread(destination, (uptr)destination->signal_handlers[type].pc);//&destination->signal_handlers[type]; + if (t->pc) + run_thread_oneshot(t, destination); switch_proc(YIELD); diff --git a/kernel/process/stack_manager.h b/kernel/process/stack_manager.h index b2a7b876..22857642 100644 --- a/kernel/process/stack_manager.h +++ b/kernel/process/stack_manager.h @@ -4,7 +4,7 @@ #include "process.h" #define stack_max 0x100000 -#define stack_max_addr 0x7ffffffff000 +#define stack_max_addr 0x7ffffffff000ULL #define stack_distance (stack_max + PAGE_SIZE) #define stack_min_addr 0x100000000000ULL diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index d190961e..67bc89e0 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -194,8 +194,14 @@ u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ syscall_depth--; if ((uptr)current_thread == (uptr)ctx) stop_current_process(current_thread->PROC_X0); - else + else { + current_thread->thread_state = STOPPED; + if (ctx->pending_thread == current_thread){ + print("Current thread was scheduled expecting result. We have it now"); + ctx->pending_thread = 0; + } switch_proc(YIELD);//TODO: proper cleanup + } return 0; } @@ -474,14 +480,14 @@ u64 syscall_signal_handler(process_t* ctx, thread_t *current_thread){ return register_signal_handler(ctx, type, (signal_handler)handler); } -// uint64_t syscall_load_fsmod(process_t *ctx){ -// system_module *mod = (system_module*)current_thread->PROC_X0; -// return load_process_module(ctx,mod); -// } +uint64_t syscall_load_fsmod(process_t *ctx, thread_t *current_thread){ + SYSCALL_ARG(system_module,mod,PROC_X0, false); + return load_process_module(ctx,mod); +} -// uint64_t syscall_unload_fsmod(process_t *ctx){ -// return unload_module(&ctx->exposed_fs); -// } +uint64_t syscall_unload_fsmod(process_t *ctx, thread_t *current_thread){ + return unload_module(&ctx->exposed_fs); +} u64 syscall_in_case_of_js(process_t *ctx, thread_t *current_thread){ panic("Shame on you\r\n\ @@ -535,8 +541,8 @@ syscall_entry syscalls[] = { [DIR_LIST_CODE] = syscall_dir_list, [FILE_STAT_CODE] = syscall_stat, [FILE_TRNC_CODE] = syscall_trunc, - // [LOAD_FSMODULE_CODE] = syscall_load_fsmod, - // [UNLOAD_FSMODULE_CODE] = syscall_unload_fsmod, + [LOAD_FSMODULE_CODE] = syscall_load_fsmod, + [UNLOAD_FSMODULE_CODE] = syscall_unload_fsmod, [SIGNAL_SEND_CODE] = syscall_signal_send, [SIGNAL_HANDLER_CODE] = syscall_signal_handler, diff --git a/kernel/utils/termhistory/termhistory.c b/kernel/utils/termhistory/termhistory.c index 37d2c1aa..e69de29b 100644 --- a/kernel/utils/termhistory/termhistory.c +++ b/kernel/utils/termhistory/termhistory.c @@ -1,14 +0,0 @@ -#include "files/system_module.h" -#include "files/stack_fs.h" - -system_module termhistory_mod = { - .name = "terminal history", - .mount = "termhistory", - .version = VERSION_NUM(0, 1, 0, 0), - .init = stackfs_init, - .open = stackfs_open, - .read = stackfs_read, - .write = stackfs_write, - .readdir = stackfs_readdir, - .getstat = stackfs_stat -}; \ No newline at end of file diff --git a/kernel/utils/utils.h b/kernel/utils/utils.h index 0b867fb2..d76fea3c 100644 --- a/kernel/utils/utils.h +++ b/kernel/utils/utils.h @@ -13,6 +13,5 @@ static inline bool load_util_mods(){ load_module(&clipboard_mod) && load_module(&language_mod) && load_module(&rng_module) && - load_module(&termhistory_mod) && true; } \ No newline at end of file diff --git a/modules/audio/virt/audio.cpp b/modules/audio/virt/audio.cpp index 8a31b79e..f6d38000 100644 --- a/modules/audio/virt/audio.cpp +++ b/modules/audio/virt/audio.cpp @@ -304,6 +304,7 @@ system_module audio_module = (system_module){ .name = "audio", .mount = "audio", .version = VERSION_NUM(0, 1, 0, 1), + .owner = 0, .init = init_audio, .fini = 0, .open = audio_open, diff --git a/modules/graph/raspi/graphics.cpp b/modules/graph/raspi/graphics.cpp index f5f5c7a7..5f356d92 100644 --- a/modules/graph/raspi/graphics.cpp +++ b/modules/graph/raspi/graphics.cpp @@ -12,7 +12,7 @@ static bool _gpu_ready; GPUDriver *gpu_driver; -bool gpu_init(){ +bool gpu_init(system_module *mod){ kprint("[GRAPH] Initializing Raspberry Pi GPU"); gpu_size preferred_screen_size = system_config.preferred_screen_size; gpu_driver = VideoCoreGPUDriver::try_init(preferred_screen_size); @@ -111,6 +111,7 @@ system_module graphics_module = { .name = "graphics", .mount = "graph", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = gpu_init, .fini = 0, .open = 0, @@ -119,5 +120,6 @@ system_module graphics_module = { .close = 0, .truncate = 0, .getstat = 0,//TODO: stat - .readdir = 0 + .readdir = 0, + .alias_info = {} }; \ No newline at end of file diff --git a/modules/graph/virt/graphics.cpp b/modules/graph/virt/graphics.cpp index 11ea2e94..0c0dad13 100644 --- a/modules/graph/virt/graphics.cpp +++ b/modules/graph/virt/graphics.cpp @@ -121,6 +121,7 @@ system_module graphics_module = { .name = "graphics", .mount = "graph", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = gpu_init, .fini = 0, .open = 0, diff --git a/modules/usb/common/usb_common.cpp b/modules/usb/common/usb_common.cpp index e64bcd02..9527131e 100644 --- a/modules/usb/common/usb_common.cpp +++ b/modules/usb/common/usb_common.cpp @@ -76,6 +76,7 @@ system_module usb_module = (system_module){ .name = "input", .mount = "in", .version = VERSION_NUM(0, 1, 0, 1), + .owner = 0, .init = input_init, .fini = 0, .open = 0, diff --git a/shared b/shared index 6a9886d8..45d6f0b2 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 6a9886d8c17551b1f16d4eb9a9711537992b48f8 +Subproject commit 45d6f0b25758f05ce143d182955e8e3f284d09a7 diff --git a/user/demo/default_process.c b/user/demo/default_process.c index 508e6110..b4f3e9cf 100644 --- a/user/demo/default_process.c +++ b/user/demo/default_process.c @@ -186,9 +186,8 @@ int copypaste(){ bool should_quit = false; bool on_quit(signal_info_t *do_not_use_this){ - printl("I'm told to quit"); should_quit = true; - // while(true); + // while (true) printl("I'm told to quit"); return true; } diff --git a/user/terminal/main.c b/user/terminal/main.c index cc0886c0..9cc93469 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -10,6 +10,8 @@ #include "files/helpers.h" #include "header_utils/screenprinter.h" #include "header_utils/composite.h" +#include "files/system_module.h" +#include "files/stack_fs.h" embedded_fmt input_format = {}; @@ -273,11 +275,33 @@ void toggle_cursor(){ refresh_input(); } +bool quit = false; + +bool termhistory_init(system_module *mod){ + quit = true; + // while (true) printl("I'm told to quit %i"); + return true; +} + +system_module termhistory_mod = { + .name = "terminal history", + .mount = "termhistory", + .version = VERSION_NUM(0, 1, 0, 0), + .init = termhistory_init, + .open = stackfs_open, + .read = stackfs_read, + .write = stackfs_write, + .readdir = stackfs_readdir, + .getstat = stackfs_stat +}; + int main(){ request_app_ctx(&ctx); screen_printer_init(dummy_draw_ctx(ctx.width, ctx.height-INPUT_HEIGHT)); + load_fsmodule(&termhistory_mod); + u32 color_buf[2] = {}; sreadf("/theme", &color_buf, sizeof(uint64_t)); if ((color_buf[0] & 0xFF000000) == 0) color_buf[0] |= 0xFF000000; @@ -300,6 +324,7 @@ int main(){ u64 last_time = get_time(); refresh_input(); while (true){ + if (quit) halt(0); // append("Bonjour %.3i \t",i++); u64 current_time = get_time(); cursor_current += (current_time-last_time); From 5ad13646846e8c9e223309157d27847b8fa38e60 Mon Sep 17 00:00:00 2001 From: di Date: Sat, 27 Jun 2026 00:00:00 +0000 Subject: [PATCH 07/65] [UFS] defer module init/deinit to process --- kernel/filesystem/modules/module_loader.c | 24 +++++++++-------------- kernel/process/scheduler.c | 2 ++ shared | 2 +- user/terminal/main.c | 5 +++-- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/kernel/filesystem/modules/module_loader.c b/kernel/filesystem/modules/module_loader.c index 5565cd53..09e3bf43 100644 --- a/kernel/filesystem/modules/module_loader.c +++ b/kernel/filesystem/modules/module_loader.c @@ -26,7 +26,7 @@ system_module root_module = { }; bool load_module_to(hash_map_t* modules, system_module *module){ - if (!module->init){ + if (module->owner == get_kernel_proc()->id && !module->init){ if (strcmp(module->mount,"/console")) kprintf("[MODULE] module not initialized due to missing initializer");//TODO: can we make printf silently fail so logging becomes easier? return false; } @@ -42,14 +42,7 @@ bool load_module_to(hash_map_t* modules, system_module *module){ return false; } if (!module->owner) module->owner = get_kernel_proc()->id; - if (module->owner != get_kernel_proc()->id){ - process_t *p = get_proc_by_pid(module->owner); - if (!p) return false; - p->fs_thread = new_thread(p, (uptr)module->init); - run_thread_oneshot(&p->fs_thread,p); - //TODO: The thread returns asyncronously, we'll need to handle that - } - if (!module->init(module)){ + if (module->owner == get_kernel_proc()->id && !module->init(module)){ if (strcmp(module->mount,"/console")) kprintf("[MODULE] failed to load module %s. Init failed",module->name); return false; } @@ -59,12 +52,12 @@ bool load_module_to(hash_map_t* modules, system_module *module){ bool unload_module_from(hash_map_t* modules, system_module *module){ if (!modules) return false; - if (!module->init) return false; - if (module->fini) { - if (module->owner != get_kernel_proc()->id){ - kprint("Can't deinit module yet"); - } else - module->fini(); + if (module->owner == get_kernel_proc()->id){ + if (!module->init) return false; + if (module->fini) { + kprint("Can't deinit module yet"); + } else + module->fini(); } hash_map_remove(modules, module->mount, strlen(module->mount), 0); return false; @@ -105,6 +98,7 @@ void iterate_root(void* key, u64 keylen, void* value){ if (count <= index) return; system_module *mod = value; + if (!mod || !mod->mount) return; if (!dir_list_fill(dir_helper, mod->mount)){ if (list_offset) *list_offset = index; return; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 83653ca0..61743785 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -718,6 +718,8 @@ u64 run_thread_oneshot(thread_t *t, process_t *p){ bool load_process_module(process_t *p, system_module *m){ p->exposed_fs = *m; + p->exposed_fs.name = string_from_literal(p->exposed_fs.name).data; + p->exposed_fs.mount = string_from_literal(p->exposed_fs.mount).data; p->exposed_fs.owner = p->id; return load_module(&p->exposed_fs); } diff --git a/shared b/shared index 45d6f0b2..af6f33f2 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 45d6f0b25758f05ce143d182955e8e3f284d09a7 +Subproject commit af6f33f22d03d504513065647d6f8038b578e936 diff --git a/user/terminal/main.c b/user/terminal/main.c index 9cc93469..c91059a4 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -278,7 +278,7 @@ void toggle_cursor(){ bool quit = false; bool termhistory_init(system_module *mod){ - quit = true; + printl("Mounting mod"); // while (true) printl("I'm told to quit %i"); return true; } @@ -287,7 +287,7 @@ system_module termhistory_mod = { .name = "terminal history", .mount = "termhistory", .version = VERSION_NUM(0, 1, 0, 0), - .init = termhistory_init, + .init = 0, .open = stackfs_open, .read = stackfs_read, .write = stackfs_write, @@ -300,6 +300,7 @@ int main(){ screen_printer_init(dummy_draw_ctx(ctx.width, ctx.height-INPUT_HEIGHT)); + stackfs_init(); load_fsmodule(&termhistory_mod); u32 color_buf[2] = {}; From 43dad15143b3dd95e6695cdc33ece8e966395ac5 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 26 Jun 2026 00:00:00 +0000 Subject: [PATCH 08/65] [PROC] main thread in process --- kernel/input/input_dispatch.c | 12 +++--- kernel/kernel_processes/kprocess_loader.c | 25 ++++++------ kernel/process/loading/elf_file.c | 20 ++++----- kernel/process/loading/process_loader.c | 14 +++---- kernel/process/process.h | 10 +---- kernel/process/scheduler.c | 50 ++++++++++++----------- kernel/process/syscall.c | 6 +-- kernel/tools/monitor_processes.c | 14 +++---- 8 files changed, 74 insertions(+), 77 deletions(-) diff --git a/kernel/input/input_dispatch.c b/kernel/input/input_dispatch.c index e28475d7..7614414a 100644 --- a/kernel/input/input_dispatch.c +++ b/kernel/input/input_dispatch.c @@ -36,7 +36,7 @@ bool register_keypress(keypress kp) { } process_t *target = focused_proc; - if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr) && !target->mm.ttbr0)) { u16 win_id = target ? target->win_id : 0; u16 skip_id = target ? target->id : 0; focused_proc = 0; @@ -47,7 +47,7 @@ bool register_keypress(keypress kp) { } target = focused_proc; - if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr) && !target->mm.ttbr0)) { focused_proc = 0; return false; } @@ -83,7 +83,7 @@ bool register_scroll(i8 scroll){ void register_event(kbd_event event){ process_t *target = focused_proc; - if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr & 0xF) && !target->mm.ttbr0)) { u16 win_id = target ? target->win_id : 0; u16 skip_id = target ? target->id : 0; focused_proc = 0; @@ -94,7 +94,7 @@ void register_event(kbd_event event){ } target = focused_proc; - if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr & 0xF) && !target->mm.ttbr0)) { focused_proc = 0; return; } @@ -174,7 +174,7 @@ void sys_focus_current(){ void sys_set_focus(int pid){ process_t *target = get_proc_by_pid(pid); - if (!target || target->state == STOPPED || !target->id || !target->pc || !target->sp || (((target->spsr & 0xF) == 0) && !target->mm.ttbr0)) return; + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr & 0xF) && !target->mm.ttbr0)) return; if (focused_proc) focused_proc->focused = false; focused_proc = target; focused_proc->focused = true; @@ -192,7 +192,7 @@ void sys_unset_focus(bool close){ if (npid) { process_t *next = get_proc_by_pid(npid); - if (next && next->focused && next->state != STOPPED && next->id && next->pc && next->sp && ((((next->spsr & 0xF) != 0) || next->mm.ttbr0))) focused_proc = next; + if (next && next->focused && next->state != STOPPED && next->id && next->main_thread.pc && next->main_thread.sp && (is_privileged(next->spsr & 0xF) || next->mm.ttbr0)) focused_proc = next; } } diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index d7a85be2..1102163d 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -57,19 +57,20 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a } register_allocation(proc->alloc_map, (void*)dmap_pa_to_kva(heap), PAGE_SIZE); - proc->stack = (stack + stack_size); - proc->stack_size = stack_size; + proc->main_thread.stack = (stack + stack_size); + proc->main_thread.stack_size = stack_size; proc->heap_phys = heap; - proc->sp = proc->stack; + proc->main_thread.sp = proc->main_thread.stack; - proc->pc = ((uintptr_t)func); - proc->regs[30] = ((uintptr_t)kernel_process_return_trampoline); + proc->main_thread.pc = ((uintptr_t)func); + proc->main_thread.regs[30] = ((uintptr_t)kernel_process_return_trampoline); proc->spsr = 0x205; + proc->main_thread.spsr = 0x205; - proc->PROC_X0 = 0; - proc->PROC_X1 = 0; + proc->main_thread.PROC_X0 = 0; + proc->main_thread.PROC_X1 = 0; if (argc > 0 && argv) { @@ -86,7 +87,7 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a if (need + 0x20 < stack_size) { - uintptr_t top = proc->stack; + uintptr_t top = proc->main_thread.stack; uintptr_t base = (top - need) & ~0xFULL; char **kargv = (char**)base; @@ -110,16 +111,16 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a kargv[argc] = 0; - proc->sp = base; - proc->PROC_X0 = argc; - proc->PROC_X1 = (uintptr_t)kargv; + proc->main_thread.sp = base; + proc->main_thread.PROC_X0 = argc; + proc->main_thread.PROC_X1 = (uintptr_t)kargv; } } make_process_fs(proc, 0); ready_process(proc); - kprintf("Kernel process %s (%i) allocated with address at %llx, stack at %llx-%llx, heap at %llx. %i argument(s)", (uintptr_t)name, proc->id, proc->pc, proc->sp - proc->stack_size, proc->sp, (uaddr_t)dmap_pa_to_kva(proc->heap_phys), argc); + kprintf("Kernel process %s (%i) allocated with address at %llx, stack at %llx-%llx, heap at %llx. %i argument(s)", (uintptr_t)name, proc->id, proc->main_thread.pc, proc->main_thread.sp - proc->main_thread.stack_size, proc->main_thread.sp, (uaddr_t)dmap_pa_to_kva(proc->heap_phys), argc); irq_restore(irq); return proc; diff --git a/kernel/process/loading/elf_file.c b/kernel/process/loading/elf_file.c index 5b3c39f9..c3b8ff80 100644 --- a/kernel/process/loading/elf_file.c +++ b/kernel/process/loading/elf_file.c @@ -127,14 +127,14 @@ uint8_t elf_to_red_permissions(uint8_t flags){ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { if (!proc || argc < 0) return false; - proc->PROC_X0 = argc; - proc->PROC_X1 = 0; - proc->sp = proc->stack; + proc->main_thread.PROC_X0 = argc; + proc->main_thread.PROC_X1 = 0; + proc->main_thread.sp = proc->main_thread.stack; if (argc == 0) return true; if (!argv) return false; - size_t stack_size = proc->mm.ttbr0 ? (size_t)(proc->mm.stack_top - proc->mm.stack_limit) : proc->stack_size; + size_t stack_size = proc->mm.ttbr0 ? (size_t)(proc->mm.stack_top - proc->mm.stack_limit) : proc->main_thread.stack_size; if (!stack_size) return false; size_t total_str = 0; @@ -150,15 +150,15 @@ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { if (argv_size > stack_size) return false; if (total_str > stack_size - argv_size) return false; - uintptr_t str_base = proc->stack - total_str; + uintptr_t str_base = proc->main_thread.stack - total_str; if (argc > UACCESS_MAX_ARGV) return false; uintptr_t arg_ptrs[UACCESS_MAX_ARGV + 1] = {}; uintptr_t sp = str_base & ~0xFULL; sp -= argv_size; if (proc->mm.ttbr0) { - proc->PROC_X1 = sp; - proc->sp = sp; + proc->main_thread.PROC_X1 = sp; + proc->main_thread.sp = sp; size_t off = 0; for (int i = 0; i < argc; i++) { @@ -173,7 +173,7 @@ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { return true; } - paddr_t str_phys = proc->stack_phys - total_str; + paddr_t str_phys = proc->main_thread.stack - total_str; size_t off = 0; for (int i = 0; i < argc; i++) { size_t len = strlen(argv[i]); @@ -190,8 +190,8 @@ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { uintptr_t *kargv = (uintptr_t*)dmap_pa_to_kva(sp_phys); for (int i = 0; i <= argc; i++) kargv[i] = arg_ptrs[i]; - proc->PROC_X1 = sp; - proc->sp = sp; + proc->main_thread.PROC_X1 = sp; + proc->main_thread.sp = sp; return true; } diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index ca6b9ce9..a543ac8b 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -368,6 +368,7 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->code_size = code_size; proc->spsr = 0; + proc->main_thread.spsr = 0; uint64_t shared_pages = 1; size_t shared_size = shared_pages * PAGE_SIZE; @@ -408,17 +409,16 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat for (uint64_t i = 0; i < shared_pages; i++) mmu_map_4kb((uint64_t*)ttbr, (uint64_t)(shared_base + (i * PAGE_SIZE)), (paddr_t)(shared_page + (i * PAGE_SIZE)), MAIR_IDX_NORMAL, MEM_EXEC | MEM_NORM, MEM_PRIV_SHARED); mm_add_vma(&proc->mm, shared_base, shared_base + shared_size, MEM_EXEC | MEM_NORM, VMA_KIND_SPECIAL, VMA_FLAG_NOFREE); - proc->stack = stack_top; - proc->stack_phys = 0; - proc->stack_size = main_stack.size; + proc->main_thread.stack = stack_top; + proc->main_thread.stack_size = main_stack.size; proc->mm.rss_stack_pages = 0; - proc->sp = proc->stack; + proc->main_thread.sp = proc->main_thread.stack; - proc->pc = (uintptr_t)(entry); - proc->regs[30] = shared_base; + proc->main_thread.pc = (uintptr_t)(entry); + proc->main_thread.regs[30] = shared_base; proc->shared_page = shared_base; - kprintf("User process %s (%i) allocated at %llx entry=%llx stack=%llx-%llx (phys=%llx-%llx) anon=%llx (phys=%llx)", name, proc->id, proc, (uint64_t)proc->pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->stack_phys, (uint64_t)proc->stack_phys, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); + kprintf("User process %s (%i) allocated at %llx entry=%llx stack=%llx-%llx anon=%llx (phys=%llx)", name, proc->id, proc, (uint64_t)proc->main_thread.pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); proc->state = BLOCKED; make_process_fs(proc,proc->bundle); diff --git a/kernel/process/process.h b/kernel/process/process.h index 7834317c..fe4ebba5 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -71,15 +71,9 @@ typedef struct thread { typedef struct process { //We use the addresses of these variables to save and restore process state - uint64_t regs[31]; // x0–x30 - uintptr_t sp; - uintptr_t pc; - uint64_t spsr; - //Not used in process saving - uintptr_t stack; - paddr_t stack_phys; - uint64_t stack_size; + thread_t main_thread; //Thread ends + uint64_t spsr; thread_t *pending_thread; uint16_t id; bool in_ready_queue; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 61743785..b862c13c 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -57,13 +57,13 @@ bool process_is_known(process_t *proc){ } bool process_has_runtime_state(process_t *proc){ - return proc && (proc->sp || proc->pc || proc->spsr || proc->stack || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); + return proc && (proc->main_thread.sp || proc->main_thread.pc || proc->spsr || proc->main_thread.stack || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); } bool process_can_run(process_t *proc){ if (!proc) return false; if (!process_is_known(proc) || proc->pending_reset) return false; - if (proc->state == STOPPED || proc->sleeping || proc->suspended || !proc->pc || !proc->sp) return false; + if (proc->state == STOPPED || proc->sleeping || proc->suspended || !proc->main_thread.pc || !proc->main_thread.sp) return false; if (!is_privileged(proc->spsr)) return !!proc->mm.ttbr0; return !proc->mm.ttbr0; } @@ -137,7 +137,7 @@ void switch_proc(ProcSwitchReason reason) { next_proc->state = RUNNING; current_proc = next_proc; - cpec = (uintptr_t)current_proc; + cpec = (uptr)¤t_proc->main_thread; if (current_proc == idle_proc) timer_disable(); else { timer_enable(); @@ -153,13 +153,13 @@ void switch_proc(ProcSwitchReason reason) { void save_syscall_return(uint64_t value){ if (!current_proc) return; - current_proc->PROC_X0 = value; + current_proc->main_thread.PROC_X0 = value; } void process_restore(){ if (!current_proc) panic("process_restore null process", 0); if (!process_is_known(current_proc)) panic("process_restore unknown process", cpec); - if (current_proc->pending_reset || current_proc->state == STOPPED || !current_proc->pc || !current_proc->sp) { + if (current_proc->pending_reset || current_proc->state == STOPPED || !current_proc->main_thread.pc || !current_proc->main_thread.sp) { if (current_proc->mm.ttbr0) { current_proc->pending_reset = true; current_proc->state = STOPPED; @@ -170,13 +170,15 @@ void process_restore(){ } panic("process_restore invalid process", cpec); } + current_proc->main_thread.spsr = current_proc->spsr; if (!is_privileged(current_proc->spsr)) { - if (!current_proc->mm.ttbr0) panic("process_restore user process without ttbr0", cpec); - if (current_proc->pc >= HIGH_VA) panic("user pc in kernel VA", current_proc->pc); + if (!current_proc->mm.ttbr0) panic("process_restore user process without ttbr0", current_proc->id); + if (current_proc->main_thread.pc >= HIGH_VA) panic("user pc in kernel VA", current_proc->main_thread.pc); mmu_ttbr0_enable_user(); } else mmu_ttbr0_disable_user(); if (current_proc->pending_thread){ if (current_proc->pending_thread->thread_state != STOPPED){ + current_proc->pending_thread->spsr = current_proc->spsr; cpec = (uptr)current_proc->pending_thread; } else { current_proc->pending_thread = 0; @@ -200,14 +202,13 @@ bool init_scheduler(){ return true; } - uintptr_t get_current_heap(){ if (current_proc->heap_phys) return (uintptr_t)dmap_pa_to_kva(current_proc->heap_phys); return current_proc->mm.mmap_bottom; } bool get_current_privilege(){ - return current_proc && (current_proc->spsr & 0b1111) != 0; + return current_proc && is_privileged(current_proc->spsr); } process_t* get_current_proc(){ @@ -257,7 +258,7 @@ void reset_process(process_t *proc){ uint16_t pid = proc->id; int32_t exit_code = proc->exit_code; - bool counted = proc->sp || proc->pc || proc->spsr || proc->stack || proc->heap_phys || proc->mm.ttbr0; + bool counted = proc->main_thread.sp || proc->main_thread.pc || proc->spsr || proc->main_thread.stack || proc->heap_phys || proc->mm.ttbr0; irq_flags_t irq = irq_save_disable(); proc->pending_reset = false; @@ -269,10 +270,10 @@ void reset_process(process_t *proc){ update_sleep_timer(); irq_restore(irq); - proc->sp = 0; - proc->pc = 0; + proc->main_thread.sp = 0; + proc->main_thread.pc = 0; proc->spsr = 0; - memset(proc->regs, 0, 31 * sizeof(proc->regs[0])); + memset(proc->main_thread.regs, 0, 31 * sizeof(proc->main_thread.regs[0])); memset(&proc->input_buffer, 0, sizeof(proc->input_buffer)); memset(&proc->event_buffer, 0, sizeof(proc->event_buffer)); proc->packet_buffer.read_index = 0; @@ -420,9 +421,8 @@ void reset_process(process_t *proc){ memset(proc->name, 0, sizeof(proc->name)); - proc->stack = 0; - proc->stack_phys = 0; - proc->stack_size = 0; + proc->main_thread.stack = 0; + proc->main_thread.stack_size = 0; proc->heap_phys = 0; memset(&proc->mm, 0, sizeof(proc->mm)); @@ -460,10 +460,11 @@ void init_main_process(){ kernel_proc->id = next_proc_index++; kernel_proc->alloc_map = make_page_index(); kernel_proc->state = BLOCKED; + kernel_proc->spsr = 0x205; kernel_proc->heap_phys = (uintptr_t)palloc(0x1000, MEM_PRIV_KERNEL, MEM_RW, false); - kernel_proc->stack_size = 0x10000; - kernel_proc->stack = (uintptr_t)palloc(kernel_proc->stack_size,MEM_PRIV_KERNEL, MEM_RW,true); - kernel_proc->sp = (uintptr_t)ksp; + kernel_proc->main_thread.stack_size = 0x10000; + kernel_proc->main_thread.stack = (uintptr_t)palloc(kernel_proc->main_thread.stack_size,MEM_PRIV_KERNEL, MEM_RW,true); + kernel_proc->main_thread.sp = (uintptr_t)ksp; kernel_proc->output = (kaddr_t)palloc(PROC_OUT_BUF, MEM_PRIV_KERNEL, MEM_RW, true); kernel_proc->output_size = 0; kernel_proc->postmortem_output = 0; @@ -472,13 +473,14 @@ void init_main_process(){ name_process(kernel_proc, "kernel"); idle_proc->state = BLOCKED; idle_proc->priority = PROC_PRIORITY_LOW; - idle_proc->stack_size = 0x4000; - uintptr_t idle_stack = (uintptr_t)palloc(idle_proc->stack_size,MEM_PRIV_KERNEL, MEM_RW,true); + idle_proc->main_thread.stack_size = 0x4000; + uintptr_t idle_stack = (uintptr_t)palloc(idle_proc->main_thread.stack_size,MEM_PRIV_KERNEL, MEM_RW,true); if (!idle_stack) panic("idle stack alloc failed", 0); - idle_proc->stack = idle_stack + idle_proc->stack_size; - idle_proc->sp = idle_proc->stack; - idle_proc->pc = (uintptr_t)idle_entry; + idle_proc->main_thread.stack = idle_stack + idle_proc->main_thread.stack_size; + idle_proc->main_thread.sp = idle_proc->main_thread.stack; + idle_proc->main_thread.pc = (uintptr_t)idle_entry; idle_proc->spsr = 0x205; + idle_proc->main_thread.spsr = 0x205; name_process(idle_proc, "idle"); proc_count++; diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 67bc89e0..c551f3c3 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -295,7 +295,7 @@ u64 syscall_socket_accept(process_t *ctx, thread_t *current_thread){ u64 syscall_socket_send(process_t *ctx, thread_t *current_thread){ uint8_t dst_kind = (uint8_t)current_thread->PROC_X1; uint16_t port = (uint16_t)current_thread->PROC_X3; - size_t size = (size_t)ctx->regs[5]; + size_t size = (size_t)current_thread->regs[5]; SYSCALL_ARG(SocketHandle,handle, PROC_X0, true); @@ -671,7 +671,7 @@ void sync_el0_handler_c(){ result = entry(proc, current_thread); } else { kprintf("Unknown syscall in process. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); - coredump(esr, elr, far, proc->sp); + coredump(esr, elr, far, current_thread->sp); syscall_depth--; stop_current_process(ec); } @@ -687,7 +687,7 @@ void sync_el0_handler_c(){ while (true); } else { kprintf("Process has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", esr, elr, far, current_thread->sp); - if (syscall_depth <= 2) coredump(esr, elr, far, proc->sp); + if (syscall_depth <= 2) coredump(esr, elr, far, current_thread->sp); syscall_depth--; stop_current_process(ec); } diff --git a/kernel/tools/monitor_processes.c b/kernel/tools/monitor_processes.c index d1c8cae1..fec1e2a0 100644 --- a/kernel/tools/monitor_processes.c +++ b/kernel/tools/monitor_processes.c @@ -41,14 +41,14 @@ uint64_t calc_heap(uintptr_t ptr){ char *procname; void print_process_info(){ - process_t *proc = get_all_processes(); + process_t *proc = get_all_processes();//TODO: awareness of threads while (proc){ if (proc->id != 0 && proc->state != STOPPED && (!procname || strcmp_case(procname,proc->name,true) == 0)){ print("Process %s [pid = %i | status = %s]",(uintptr_t)proc->name,proc->id,(uintptr_t)parse_proc_state(proc->state)); - print("Stack: %x (%x). SP: %x",proc->stack, proc->stack_size, proc->sp); + print("Stack: %x (%x). SP: %x",proc->main_thread.stack, proc->main_thread.stack_size, proc->main_thread.sp); print("Heap: %x (%x)",proc->mm.mmap_bottom, calc_heap(proc->heap_phys)); - print("Flags: %x", proc->spsr); - print("PC: %x",proc->pc); + print("Flags: %x", proc->main_thread.spsr); + print("PC: %x",proc->main_thread.pc); } proc = proc->process_next; } @@ -126,16 +126,16 @@ void draw_process_view(){ fb_draw_string(&ctx,name.data, xo, name_y, scale, system_theme.bg_color); fb_draw_string(&ctx,state.data, xo, state_y, scale, system_theme.bg_color); - string pc = string_from_hex(proc->pc); + string pc = string_from_hex(proc->main_thread.pc); fb_draw_string(&ctx,pc.data, xo, pc_y, scale, system_theme.bg_color); string_free(pc); - draw_memory("Stack", xo, stack_y, stack_width, stack_height, proc->stack - proc->sp, proc->stack_size ? proc->stack_size : 1); + draw_memory("Stack", xo, stack_y, stack_width, stack_height, proc->main_thread.stack - proc->main_thread.sp, proc->main_thread.stack_size ? proc->main_thread.stack_size : 1); uint64_t heap = proc->mm.ttbr0 ? (proc->mm.rss_anon_pages * PAGE_SIZE) : calc_heap(proc->heap_phys); uint64_t heap_limit = proc->mm.ttbr0 ? (uint64_t)(proc->mm.mmap_top - proc->mm.mmap_bottom) : ((heap + 0xFFF) & ~0xFFF); draw_memory("Heap", xo + stack_width + 50, stack_y, stack_width, stack_height, heap, heap_limit ? heap_limit : PAGE_SIZE); - string flags = string_format("Flags: %x", proc->spsr); + string flags = string_format("Flags: %x", proc->main_thread.spsr); fb_draw_string(&ctx, flags.data, xo, flags_y, scale, system_theme.bg_color); string_free(name); string_free(state); From 1107f848fe22b4acc0fce8ccccbb6c8bdf5af0e0 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 26 Jun 2026 00:00:00 +0000 Subject: [PATCH 09/65] [PROC] in_ready_queue moved to just use state --- kernel/process/process.h | 2 +- kernel/process/scheduler.c | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/kernel/process/process.h b/kernel/process/process.h index fe4ebba5..ee1039c4 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -67,6 +67,7 @@ typedef struct thread { uint64_t stack_size; u16 pid; process_state thread_state; + struct thread *next; } thread_t; typedef struct process { @@ -76,7 +77,6 @@ typedef struct process { uint64_t spsr; thread_t *pending_thread; uint16_t id; - bool in_ready_queue; bool sleeping; bool suspended; uint64_t wake_at_msec; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index b862c13c..ec800290 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -73,10 +73,9 @@ bool process_can_reset(process_t *proc){ } void enqueue_ready_process(process_t *proc){ - if (!proc || proc == idle_proc || proc->in_ready_queue) return; + if (!proc || proc == idle_proc || proc->state == READY) return; if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); if (!cqueue_enqueue(&ready_queue, &proc)) panic("ready enqueue failed", proc->id); - proc->in_ready_queue = true; proc->state = READY; } @@ -124,7 +123,6 @@ void switch_proc(ProcSwitchReason reason) { process_t *queued = 0; if (!cqueue_dequeue(&ready_queue, &queued)) break; if (!queued) continue; - if (process_is_known(queued)) queued->in_ready_queue = false; if (queued->state != READY || !process_can_run(queued)) continue; next_proc = queued; break; @@ -164,7 +162,6 @@ void process_restore(){ current_proc->pending_reset = true; current_proc->state = STOPPED; current_proc->sleeping = false; - current_proc->in_ready_queue = false; switch_proc(HALT); panic("process_restore recovery returned", cpec); } @@ -229,7 +226,7 @@ bool scheduler_in_idle(){ void ready_process(process_t *proc){ irq_flags_t irq = irq_save_disable(); - if (!proc || !proc->id || proc->state == STOPPED || proc->sleeping || proc->in_ready_queue || proc->pending_reset) { + if (!proc || !proc->id || proc->state == STOPPED || proc->sleeping || proc->pending_reset) { irq_restore(irq); return; } @@ -264,7 +261,6 @@ void reset_process(process_t *proc){ proc->pending_reset = false; proc->sleeping = false; proc->wake_at_msec = 0; - proc->in_ready_queue = false; remove_sleeping_process(proc, pid); @@ -506,7 +502,6 @@ process_t* init_process(){ proc->exit_code = 0; proc->state = BLOCKED; proc->priority = PROC_PRIORITY_LOW; - proc->in_ready_queue = false; proc->sleeping = false; proc->wake_at_msec = 0; proc->pending_reset = false; @@ -567,7 +562,6 @@ void stop_process(uint16_t pid, int32_t exit_code){ kprintf("[SCHEDULER] Stop process %i with code %i",proc->id,proc->exit_code); - proc->in_ready_queue = false; proc->sleeping = false; proc->wake_at_msec = 0; if (proc->focused) From f372a78f46a26881aa8c1e252571df647f264ce1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Fri, 26 Jun 2026 00:00:00 +0000 Subject: [PATCH 10/65] [PROC] spsr to thread --- kernel/exceptions/irq.c | 2 +- kernel/input/input_dispatch.c | 12 +++++------ kernel/kernel_processes/kprocess_loader.c | 1 - kernel/process/loading/process_loader.c | 1 - kernel/process/process.h | 5 +++-- kernel/process/scheduler.c | 25 +++++++++++------------ kernel/process/stack_manager.c | 4 ++-- kernel/process/syscall.c | 2 +- 8 files changed, 25 insertions(+), 27 deletions(-) diff --git a/kernel/exceptions/irq.c b/kernel/exceptions/irq.c index 8f4dd08f..26467229 100644 --- a/kernel/exceptions/irq.c +++ b/kernel/exceptions/irq.c @@ -107,7 +107,7 @@ void irq_el1_handler() { if (irq == IRQ_TIMER) { bool can_preempt = true; - if (get_current_proc() && get_current_proc()->mm.ttbr0 && (get_current_proc()->spsr & 0xF) != 0) can_preempt = false; + if (get_current_proc() && get_current_proc()->mm.ttbr0 && is_privileged(get_current_proc())) can_preempt = false; if (RPI_BOARD != 3) write32(GICC_BASE + 0x10, irq); syscall_depth--; if (can_preempt) switch_proc(INTERRUPT); diff --git a/kernel/input/input_dispatch.c b/kernel/input/input_dispatch.c index 7614414a..4752f0b9 100644 --- a/kernel/input/input_dispatch.c +++ b/kernel/input/input_dispatch.c @@ -36,7 +36,7 @@ bool register_keypress(keypress kp) { } process_t *target = focused_proc; - if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) { u16 win_id = target ? target->win_id : 0; u16 skip_id = target ? target->id : 0; focused_proc = 0; @@ -47,7 +47,7 @@ bool register_keypress(keypress kp) { } target = focused_proc; - if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) { focused_proc = 0; return false; } @@ -83,7 +83,7 @@ bool register_scroll(i8 scroll){ void register_event(kbd_event event){ process_t *target = focused_proc; - if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr & 0xF) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) { u16 win_id = target ? target->win_id : 0; u16 skip_id = target ? target->id : 0; focused_proc = 0; @@ -94,7 +94,7 @@ void register_event(kbd_event event){ } target = focused_proc; - if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr & 0xF) && !target->mm.ttbr0)) { + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) { focused_proc = 0; return; } @@ -174,7 +174,7 @@ void sys_focus_current(){ void sys_set_focus(int pid){ process_t *target = get_proc_by_pid(pid); - if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target->spsr & 0xF) && !target->mm.ttbr0)) return; + if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) return; if (focused_proc) focused_proc->focused = false; focused_proc = target; focused_proc->focused = true; @@ -192,7 +192,7 @@ void sys_unset_focus(bool close){ if (npid) { process_t *next = get_proc_by_pid(npid); - if (next && next->focused && next->state != STOPPED && next->id && next->main_thread.pc && next->main_thread.sp && (is_privileged(next->spsr & 0xF) || next->mm.ttbr0)) focused_proc = next; + if (next && next->focused && next->state != STOPPED && next->id && next->main_thread.pc && next->main_thread.sp && (is_privileged(next) || next->mm.ttbr0)) focused_proc = next; } } diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index 1102163d..c52ae04d 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -66,7 +66,6 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a proc->main_thread.pc = ((uintptr_t)func); proc->main_thread.regs[30] = ((uintptr_t)kernel_process_return_trampoline); - proc->spsr = 0x205; proc->main_thread.spsr = 0x205; proc->main_thread.PROC_X0 = 0; diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index a543ac8b..2fe5dbff 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -367,7 +367,6 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->code = dest; proc->code_size = code_size; - proc->spsr = 0; proc->main_thread.spsr = 0; uint64_t shared_pages = 1; diff --git a/kernel/process/process.h b/kernel/process/process.h index ee1039c4..33c2c431 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -74,7 +74,6 @@ typedef struct process { //We use the addresses of these variables to save and restore process state thread_t main_thread; //Thread ends - uint64_t spsr; thread_t *pending_thread; uint16_t id; bool sleeping; @@ -121,7 +120,9 @@ typedef struct process { struct process *process_next; } process_t; -#define is_privileged(spsr) (spsr & 0xf) +static inline bool is_privileged(process_t *proc){ + return proc->main_thread.spsr & 0xf; +} //Helper functions for accessing registers mapped to scratch regs #define PROC_X0 regs[0] diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index ec800290..93c73dca 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -57,14 +57,14 @@ bool process_is_known(process_t *proc){ } bool process_has_runtime_state(process_t *proc){ - return proc && (proc->main_thread.sp || proc->main_thread.pc || proc->spsr || proc->main_thread.stack || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); + return proc && (proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); } bool process_can_run(process_t *proc){ if (!proc) return false; if (!process_is_known(proc) || proc->pending_reset) return false; if (proc->state == STOPPED || proc->sleeping || proc->suspended || !proc->main_thread.pc || !proc->main_thread.sp) return false; - if (!is_privileged(proc->spsr)) return !!proc->mm.ttbr0; + if (!is_privileged(proc)) return !!proc->mm.ttbr0; return !proc->mm.ttbr0; } @@ -167,15 +167,15 @@ void process_restore(){ } panic("process_restore invalid process", cpec); } - current_proc->main_thread.spsr = current_proc->spsr; - if (!is_privileged(current_proc->spsr)) { + + if (!is_privileged(current_proc)) { if (!current_proc->mm.ttbr0) panic("process_restore user process without ttbr0", current_proc->id); if (current_proc->main_thread.pc >= HIGH_VA) panic("user pc in kernel VA", current_proc->main_thread.pc); mmu_ttbr0_enable_user(); } else mmu_ttbr0_disable_user(); if (current_proc->pending_thread){ if (current_proc->pending_thread->thread_state != STOPPED){ - current_proc->pending_thread->spsr = current_proc->spsr; + current_proc->pending_thread->spsr = current_proc->main_thread.spsr; cpec = (uptr)current_proc->pending_thread; } else { current_proc->pending_thread = 0; @@ -205,7 +205,7 @@ uintptr_t get_current_heap(){ } bool get_current_privilege(){ - return current_proc && is_privileged(current_proc->spsr); + return current_proc && is_privileged(current_proc); } process_t* get_current_proc(){ @@ -255,7 +255,7 @@ void reset_process(process_t *proc){ uint16_t pid = proc->id; int32_t exit_code = proc->exit_code; - bool counted = proc->main_thread.sp || proc->main_thread.pc || proc->spsr || proc->main_thread.stack || proc->heap_phys || proc->mm.ttbr0; + bool counted = proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack || proc->heap_phys || proc->mm.ttbr0; irq_flags_t irq = irq_save_disable(); proc->pending_reset = false; @@ -268,7 +268,7 @@ void reset_process(process_t *proc){ irq_restore(irq); proc->main_thread.sp = 0; proc->main_thread.pc = 0; - proc->spsr = 0; + proc->main_thread.spsr = 0; memset(proc->main_thread.regs, 0, 31 * sizeof(proc->main_thread.regs[0])); memset(&proc->input_buffer, 0, sizeof(proc->input_buffer)); memset(&proc->event_buffer, 0, sizeof(proc->event_buffer)); @@ -456,7 +456,7 @@ void init_main_process(){ kernel_proc->id = next_proc_index++; kernel_proc->alloc_map = make_page_index(); kernel_proc->state = BLOCKED; - kernel_proc->spsr = 0x205; + kernel_proc->main_thread.spsr = 0x205; kernel_proc->heap_phys = (uintptr_t)palloc(0x1000, MEM_PRIV_KERNEL, MEM_RW, false); kernel_proc->main_thread.stack_size = 0x10000; kernel_proc->main_thread.stack = (uintptr_t)palloc(kernel_proc->main_thread.stack_size,MEM_PRIV_KERNEL, MEM_RW,true); @@ -475,7 +475,6 @@ void init_main_process(){ idle_proc->main_thread.stack = idle_stack + idle_proc->main_thread.stack_size; idle_proc->main_thread.sp = idle_proc->main_thread.stack; idle_proc->main_thread.pc = (uintptr_t)idle_entry; - idle_proc->spsr = 0x205; idle_proc->main_thread.spsr = 0x205; name_process(idle_proc, "idle"); @@ -687,9 +686,9 @@ thread_t new_thread(process_t *proc, uptr entry_point){ .sp = stack.top, .stack_size = stack.size, .stack = stack.top, - .spsr = proc->spsr + .spsr = proc->main_thread.spsr }; - t.regs[30] = is_privileged(proc->spsr) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32); + t.regs[30] = is_privileged(proc) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32); return t; } @@ -701,7 +700,7 @@ u64 run_thread_oneshot(thread_t *t, process_t *p){ mmu_ttbr0_enable_user(); } t->sp = t->stack-sizeof(system_module);//TODO: stack needs not be reset past args - t->spsr = p->spsr; + t->spsr = p->main_thread.spsr; t->thread_state = RUNNING; cpec = (uptr)t; kprintf("STACK %llx and shared on %llx. Running %llx, after which %llx",t->sp,p->shared_page,t->pc,t->regs[30]); diff --git a/kernel/process/stack_manager.c b/kernel/process/stack_manager.c index 9140721f..cad76233 100644 --- a/kernel/process/stack_manager.c +++ b/kernel/process/stack_manager.c @@ -2,7 +2,7 @@ #include "exceptions/exception_handler.h" uptr next_stack_addr(process_t *proc){ - if (is_privileged(proc->spsr)) return 0; + if (is_privileged(proc)) return 0; for (uptr start = stack_max_addr; start > stack_min_addr; start -= 0x100000000000){ vma *m = mm_find_vma(&proc->mm, start-stack_max); if (!m){ @@ -14,7 +14,7 @@ uptr next_stack_addr(process_t *proc){ } stack_t new_stack(process_t *proc){ - uptr stack_top = is_privileged(proc->spsr) ? (uptr)palloc(stack_max, MEM_PRIV_KERNEL, MEM_RW, true) : next_stack_addr(proc); + uptr stack_top = is_privileged(proc) ? (uptr)palloc(stack_max, MEM_PRIV_KERNEL, MEM_RW, true) : next_stack_addr(proc); if (!stack_top) return (stack_t){}; uptr stack_limit = stack_top - stack_max; print("New stack at %llx-%llx",stack_limit,stack_top); diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index c551f3c3..dc8f45bc 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -231,7 +231,7 @@ u64 syscall_kill_process(process_t *ctx, thread_t *current_thread) { process_t *target = get_proc_by_pid(pid); if (!target || target->state == STOPPED) return 0; if (target->id == 1) return 0; - if ((target->spsr & 0xF) != 0) return 0; + if (is_privileged(target)) return 0; if (!ctx->win_id || target->win_id != ctx->win_id) return 0; stop_process(pid, -9); From 17dbfb43d35e311da123ca338ab8c0c186acbf2b Mon Sep 17 00:00:00 2001 From: di Date: Mon, 29 Jun 2026 00:00:00 +0000 Subject: [PATCH 11/65] [DOS] desktop zoom --- kernel/exceptions/timer.c | 2 +- kernel/kernel_processes/windows/dos.c | 14 ++++++++------ kernel/process/loading/process_loader.c | 1 + kernel/theme/theme.c | 2 ++ kernel/theme/theme.h | 1 + 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/kernel/exceptions/timer.c b/kernel/exceptions/timer.c index a7582880..ca996028 100644 --- a/kernel/exceptions/timer.c +++ b/kernel/exceptions/timer.c @@ -83,7 +83,7 @@ uint64_t timer_now() { asm volatile ("mrs %0, cntvct_el0" : "=r"(val)); return val; } - +//TODO: do we want more precision since we have it? uint64_t timer_now_msec() { uint64_t ticks = timer_now(); uint64_t freq = rd_cntfrq_el0(); diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 4701b752..6df6f1fd 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -289,12 +289,14 @@ int window_system(){ } drawing = false; } - // i8 scroll = get_raw_mouse_in().scroll; - // if (scroll){ - // zoom_scale += -scroll; - // zoom_scale = clamp(zoom_scale, 1, 5); - // dirty_windows = true; - // } + if (system_theme.use_desktop_zoom){ + i8 scroll = get_raw_mouse_in().scroll; + if (scroll){ + zoom_scale += -scroll; + zoom_scale = clamp(zoom_scale, 1, 5); + dirty_windows = true; + } + } disable_interrupt(); if (dirty_windows){ active = true; diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index a543ac8b..63f7faed 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -316,6 +316,7 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat return 0; } if (!shared_page) { + //TODO: can we make the page auto-generated with the codes for svcs? shared_page = palloc_inner(PAGE_SIZE, MEM_PRIV_SHARED, MEM_EXEC, true, false); *(u32*)(uptr)dmap_pa_to_kva(shared_page) = aarch64_svc(HALT_CODE); *(u32*)(uptr)dmap_pa_to_kva(shared_page+sizeof(u32)) = aarch64_svc(HALT_THREAD_CODE); diff --git a/kernel/theme/theme.c b/kernel/theme/theme.c index de3139b8..c85fd39f 100644 --- a/kernel/theme/theme.c +++ b/kernel/theme/theme.c @@ -31,6 +31,7 @@ system_theme_t system_theme = { .cursor_color_deselected = CURSOR_COLOR_DESELECTED, .cursor_color_selected = CURSOR_COLOR_SELECTED, .use_window_shadows = true, + .use_desktop_zoom = true, }; system_config_t system_config = { @@ -103,6 +104,7 @@ void parse_theme_kvp(string_slice key, string_slice value, void *context){ parse_toml(cursor_color_deselected, system_theme, parse_hex_u64); parse_toml(cursor_color_selected, system_theme, parse_hex_u64); parse_toml(use_window_shadows, system_theme, parse_int_u64); + parse_toml(use_desktop_zoom, system_theme, parse_int_u64); parse_toml_str(panic_text, system_config); parse_toml_str(system_name, system_config); diff --git a/kernel/theme/theme.h b/kernel/theme/theme.h index cf194cd8..2e866156 100644 --- a/kernel/theme/theme.h +++ b/kernel/theme/theme.h @@ -26,6 +26,7 @@ typedef struct { u32 cursor_color_deselected; u32 cursor_color_selected; bool use_window_shadows; + bool use_desktop_zoom; } system_theme_t; typedef struct { From 194cdb01be54e948b94b6620e6f17899b39235cb Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 30 Jun 2026 00:00:00 +0000 Subject: [PATCH 12/65] [PROC] proper scheduling for threads --- kernel/kernel_processes/kprocess_loader.c | 2 +- kernel/process/loading/process_loader.c | 2 +- kernel/process/process.h | 7 +- kernel/process/scheduler.c | 107 +++++++++++++--------- kernel/process/scheduler.h | 5 +- kernel/process/signals/signals.c | 7 +- kernel/process/syscall.c | 7 +- 7 files changed, 80 insertions(+), 57 deletions(-) diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index c52ae04d..1c078c51 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -119,7 +119,7 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a make_process_fs(proc, 0); ready_process(proc); - kprintf("Kernel process %s (%i) allocated with address at %llx, stack at %llx-%llx, heap at %llx. %i argument(s)", (uintptr_t)name, proc->id, proc->main_thread.pc, proc->main_thread.sp - proc->main_thread.stack_size, proc->main_thread.sp, (uaddr_t)dmap_pa_to_kva(proc->heap_phys), argc); + kprintf("[NEW PROC:K] process %s (pid: %i main tid: %i) allocated with address at %llx, stack at %llx-%llx, heap at %llx. %i argument(s)", (uintptr_t)name, proc->id, proc->main_thread.tid, proc->main_thread.pc, proc->main_thread.sp - proc->main_thread.stack_size, proc->main_thread.sp, (uaddr_t)dmap_pa_to_kva(proc->heap_phys), argc); irq_restore(irq); return proc; diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index 2fe5dbff..08043db7 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -417,7 +417,7 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->main_thread.pc = (uintptr_t)(entry); proc->main_thread.regs[30] = shared_base; proc->shared_page = shared_base; - kprintf("User process %s (%i) allocated at %llx entry=%llx stack=%llx-%llx anon=%llx (phys=%llx)", name, proc->id, proc, (uint64_t)proc->main_thread.pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); + kprintf("[NEW PROC:U]: %s (pid: %i, main tid: %i) allocated at %llx entry=%llx stack=%llx-%llx anon=%llx (phys=%llx)", name, proc->id, proc->main_thread.tid, proc, (uint64_t)proc->main_thread.pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); proc->state = BLOCKED; make_process_fs(proc,proc->bundle); diff --git a/kernel/process/process.h b/kernel/process/process.h index 33c2c431..8cc22159 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -62,21 +62,20 @@ typedef struct thread { uintptr_t sp; uintptr_t pc; uint64_t spsr; - //Not used in process saving + //Not used in context saving uintptr_t stack; uint64_t stack_size; u16 pid; + u16 tid; process_state thread_state; struct thread *next; } thread_t; typedef struct process { - //We use the addresses of these variables to save and restore process state thread_t main_thread; - //Thread ends - thread_t *pending_thread; uint16_t id; bool sleeping; + thread_t *current_thread;//NOTE: temporary bool suspended; uint64_t wake_at_msec; paddr_t heap_phys; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 93c73dca..7747850f 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -25,6 +25,21 @@ extern void save_pc_interrupt(uintptr_t ptr); extern void restore_context(uintptr_t ptr); +void *proc_mem_page; + +static inline void* proc_palloc(size_t s){ + return palloc(s, MEM_PRIV_KERNEL, MEM_RW, true); +} + +static inline void* proc_alloc(size_t s){ + if (!proc_mem_page) proc_mem_page = proc_palloc(PAGE_SIZE); + return allocate(proc_mem_page, s, proc_palloc); +} + +thread_t* alloc_thread(){ + return proc_alloc(sizeof(thread_t)); +} + static process_t *current_proc = 0; static process_t *kernel_proc = 0; static process_t *idle_proc = 0; @@ -119,13 +134,19 @@ void switch_proc(ProcSwitchReason reason) { else ready_process(prev); } - while (!cqueue_is_empty(&ready_queue)) { - process_t *queued = 0; - if (!cqueue_dequeue(&ready_queue, &queued)) break; - if (!queued) continue; - if (queued->state != READY || !process_can_run(queued)) continue; - next_proc = queued; - break; + if (prev->current_thread->next){ + do { + prev->current_thread = prev->current_thread->next; + } while (prev->current_thread && prev->current_thread->thread_state != RUNNING && prev->current_thread->thread_state != READY); + } else { + while (!cqueue_is_empty(&ready_queue)) { + process_t *queued = 0; + if (!cqueue_dequeue(&ready_queue, &queued)) break; + if (!queued) continue; + if (queued->state != READY || !process_can_run(queued)) continue; + next_proc = queued; + break; + } } if (!next_proc && current_proc && current_proc != idle_proc && current_proc->state == RUNNING && process_can_run(current_proc)) next_proc = current_proc; @@ -133,9 +154,10 @@ void switch_proc(ProcSwitchReason reason) { if (!next_proc || !process_can_run(next_proc)) panic("no runnable process", 0); //if (next_proc == idle_proc && prev != idle_proc) kprint("entering idle"); + if (!next_proc->current_thread) next_proc->current_thread = &next_proc->main_thread; next_proc->state = RUNNING; current_proc = next_proc; - cpec = (uptr)¤t_proc->main_thread; + cpec = (uptr)next_proc->current_thread; if (current_proc == idle_proc) timer_disable(); else { timer_enable(); @@ -173,14 +195,6 @@ void process_restore(){ if (current_proc->main_thread.pc >= HIGH_VA) panic("user pc in kernel VA", current_proc->main_thread.pc); mmu_ttbr0_enable_user(); } else mmu_ttbr0_disable_user(); - if (current_proc->pending_thread){ - if (current_proc->pending_thread->thread_state != STOPPED){ - current_proc->pending_thread->spsr = current_proc->main_thread.spsr; - cpec = (uptr)current_proc->pending_thread; - } else { - current_proc->pending_thread = 0; - } - } restore_context(cpec); } @@ -676,39 +690,50 @@ void wake_processes(){ irq_restore(irq); } -thread_t new_thread(process_t *proc, uptr entry_point){ +void unschedule_thread(process_t *proc, thread_t *t){ + if (!proc || !t || proc->id != t->pid) return; + thread_t *prev = &proc->main_thread; + thread_t *current = prev->next; + if (proc->current_thread == t) proc->current_thread = prev; + while (current) { + if (t == current){ + prev->next = current->next; + return; + } + prev = current; + current = current->next; + } +} + +void schedule_thread(process_t *proc, thread_t *t){ + if (!proc || !t || proc->id != t->pid) return; + thread_t *current = &proc->main_thread; + while (current){ + if (!current->next){ + current->next = t; + kprintf("[SCHEDULER] scheduled thread %i for %i. pc %llx",t->tid,t->pid,t->pc); + t->thread_state = RUNNING; + return; + } + current = current->next; + } +} + +thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point){ stack_t stack = new_stack(proc); - if (!stack.top || !stack.size) return (thread_t){}; - thread_t t = { + if (!proc || !stack.top || !stack.size || !addr) return 0; + *addr = (thread_t){ .pc = entry_point, .pid = proc->id, .regs = {}, .sp = stack.top, .stack_size = stack.size, .stack = stack.top, - .spsr = proc->main_thread.spsr + .spsr = spsr, + // .state = BLOCKED, }; - t.regs[30] = is_privileged(proc) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32); - return t; -} - -u64 run_thread_oneshot(thread_t *t, process_t *p){ - process_t *cproc = current_proc; - if (p != cproc){ - if (p->mm.ttbr0) mmu_asid_ensure(&p->mm); - mmu_swap_ttbr(p->mm.ttbr0 ? &p->mm : 0); - mmu_ttbr0_enable_user(); - } - t->sp = t->stack-sizeof(system_module);//TODO: stack needs not be reset past args - t->spsr = p->main_thread.spsr; - t->thread_state = RUNNING; - cpec = (uptr)t; - kprintf("STACK %llx and shared on %llx. Running %llx, after which %llx",t->sp,p->shared_page,t->pc,t->regs[30]); - timer_reset(p->priority); - p->pending_thread = t; - restore_context(cpec); - panic("Somehow the thread has returned",(uptr)t); - return 0; + addr->regs[30] = is_privileged(proc) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32); + return addr; } bool load_process_module(process_t *p, system_module *m){ diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 276d425c..384892fb 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -62,7 +62,10 @@ bool get_current_privilege(); uint16_t process_count(); process_t *get_all_processes(); -thread_t new_thread(process_t *proc, uptr entry_point); +thread_t* alloc_thread(); +thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point); +void unschedule_thread(process_t *proc, thread_t *t); +void schedule_thread(process_t *proc, thread_t *t); bool init_scheduler(); diff --git a/kernel/process/signals/signals.c b/kernel/process/signals/signals.c index b5887e3d..c365b437 100644 --- a/kernel/process/signals/signals.c +++ b/kernel/process/signals/signals.c @@ -14,7 +14,7 @@ bool register_signal_handler(process_t *proc, signal_types type, signal_handler return false; } kprint("Signal handler added"); - proc->signal_handlers[type] = new_thread(proc, (uptr)handler); + new_thread(proc, &proc->signal_handlers[type], proc->main_thread.spsr, (uptr)handler); return true; } @@ -30,10 +30,9 @@ bool send_signal_proc_proc(signal_types type, i64 value, process_t *source, proc return true; } - thread_t *t = zalloc(sizeof(thread_t)); - *t = new_thread(destination, (uptr)destination->signal_handlers[type].pc);//&destination->signal_handlers[type]; + thread_t *t = &destination->signal_handlers[type]; if (t->pc) - run_thread_oneshot(t, destination); + schedule_thread(destination,t); switch_proc(YIELD); diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index dc8f45bc..3a8d3932 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -192,14 +192,11 @@ u64 syscall_halt(process_t *ctx, thread_t *current_thread){ u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ kprintf("Thread has ended with code %i",current_thread->PROC_X0); syscall_depth--; - if ((uptr)current_thread == (uptr)ctx) + if (current_thread == &ctx->main_thread) stop_current_process(current_thread->PROC_X0); else { current_thread->thread_state = STOPPED; - if (ctx->pending_thread == current_thread){ - print("Current thread was scheduled expecting result. We have it now"); - ctx->pending_thread = 0; - } + unschedule_thread(ctx, current_thread); switch_proc(YIELD);//TODO: proper cleanup } return 0; From 1bdedeaf015b7425375184563272c2037dfc757f Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 30 Jun 2026 00:00:00 +0000 Subject: [PATCH 13/65] [THREAD] thread count and ids --- kernel/process/process.h | 7 +++++++ kernel/process/scheduler.c | 8 +++++++- kernel/process/stack_manager.h | 6 ------ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/kernel/process/process.h b/kernel/process/process.h index 8cc22159..d5a0d260 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -57,6 +57,12 @@ typedef struct { typedef enum { STOPPED, READY, RUNNING, BLOCKED } process_state; +typedef struct { + uptr top; + size_t max; + size_t size; +} stack_t; + typedef struct thread { uint64_t regs[31]; // x0–x30 uintptr_t sp; @@ -114,6 +120,7 @@ typedef struct process { thread_t fs_thread; mm_struct mm; int thread_count; + int thread_ids; environment_data environment; uptr shared_page; struct process *process_next; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 7747850f..116ad146 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -694,9 +694,13 @@ void unschedule_thread(process_t *proc, thread_t *t){ if (!proc || !t || proc->id != t->pid) return; thread_t *prev = &proc->main_thread; thread_t *current = prev->next; - if (proc->current_thread == t) proc->current_thread = prev; + if (proc->current_thread == t){ + proc->thread_count--; + proc->current_thread = prev; + } while (current) { if (t == current){ + proc->thread_count--; prev->next = current->next; return; } @@ -711,6 +715,7 @@ void schedule_thread(process_t *proc, thread_t *t){ while (current){ if (!current->next){ current->next = t; + proc->thread_count++; kprintf("[SCHEDULER] scheduled thread %i for %i. pc %llx",t->tid,t->pid,t->pc); t->thread_state = RUNNING; return; @@ -730,6 +735,7 @@ thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point .stack_size = stack.size, .stack = stack.top, .spsr = spsr, + .tid = ++proc->thread_ids // .state = BLOCKED, }; addr->regs[30] = is_privileged(proc) ? (uptr)kernel_thread_return_trampoline : proc->shared_page+sizeof(u32); diff --git a/kernel/process/stack_manager.h b/kernel/process/stack_manager.h index 22857642..0f7a780f 100644 --- a/kernel/process/stack_manager.h +++ b/kernel/process/stack_manager.h @@ -8,10 +8,4 @@ #define stack_distance (stack_max + PAGE_SIZE) #define stack_min_addr 0x100000000000ULL -typedef struct { - uptr top; - size_t max; - size_t size; -} stack_t; - stack_t new_stack(process_t *proc); \ No newline at end of file From 12b74c2b4b8b4277d3ff783ebb5c0d02f1dd26f1 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 30 Jun 2026 00:00:00 +0000 Subject: [PATCH 14/65] [PROC] kernel proc mem cleanup --- kernel/process/scheduler.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 116ad146..50fcca24 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -471,14 +471,7 @@ void init_main_process(){ kernel_proc->alloc_map = make_page_index(); kernel_proc->state = BLOCKED; kernel_proc->main_thread.spsr = 0x205; - kernel_proc->heap_phys = (uintptr_t)palloc(0x1000, MEM_PRIV_KERNEL, MEM_RW, false); - kernel_proc->main_thread.stack_size = 0x10000; - kernel_proc->main_thread.stack = (uintptr_t)palloc(kernel_proc->main_thread.stack_size,MEM_PRIV_KERNEL, MEM_RW,true); kernel_proc->main_thread.sp = (uintptr_t)ksp; - kernel_proc->output = (kaddr_t)palloc(PROC_OUT_BUF, MEM_PRIV_KERNEL, MEM_RW, true); - kernel_proc->output_size = 0; - kernel_proc->postmortem_output = 0; - kernel_proc->postmortem_output_size = 0; kernel_proc->priority = PROC_PRIORITY_LOW; name_process(kernel_proc, "kernel"); idle_proc->state = BLOCKED; From 0968f8d02c572da5c311048c74b428204af5e158 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 30 Jun 2026 00:00:00 +0000 Subject: [PATCH 15/65] [PROC] main thread with new_thread --- kernel/kernel_processes/kprocess_loader.c | 25 ++--------------------- kernel/process/loading/process_loader.c | 21 +++++-------------- kernel/process/process.h | 4 +++- kernel/process/scheduler.c | 21 +++++++++++-------- kernel/process/stack_manager.c | 7 ++++++- 5 files changed, 28 insertions(+), 50 deletions(-) diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index 1c078c51..1595c1ce 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -38,38 +38,17 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a name_process(proc, name); - uint64_t stack_size = 0x10000; - - uintptr_t stack = (uintptr_t)palloc(stack_size, MEM_PRIV_KERNEL, MEM_RW, true); - if (!stack) { - reset_process(proc); - irq_restore(irq); - return 0; - } - register_allocation(proc->alloc_map, (void*)stack, stack_size); - uintptr_t heap = (uintptr_t)palloc(PAGE_SIZE, MEM_PRIV_KERNEL, MEM_RW, false); if (!heap) { - free_registered(proc->alloc_map, (void*)stack); reset_process(proc); irq_restore(irq); return 0; } register_allocation(proc->alloc_map, (void*)dmap_pa_to_kva(heap), PAGE_SIZE); - proc->main_thread.stack = (stack + stack_size); - proc->main_thread.stack_size = stack_size; - proc->heap_phys = heap; - - proc->main_thread.sp = proc->main_thread.stack; - proc->main_thread.pc = ((uintptr_t)func); - proc->main_thread.regs[30] = ((uintptr_t)kernel_process_return_trampoline); - proc->main_thread.spsr = 0x205; - - proc->main_thread.PROC_X0 = 0; - proc->main_thread.PROC_X1 = 0; + new_thread(proc, &proc->main_thread, 0x205, (uptr)func); if (argc > 0 && argv) { @@ -84,7 +63,7 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a uint64_t need = argvs + str_total; need = (need + 0xF) & ~0xFULL; - if (need + 0x20 < stack_size) { + if (need + 0x20 < proc->main_thread.stack_info.size) { uintptr_t top = proc->main_thread.stack; uintptr_t base = (top - need) & ~0xFULL; diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index 83738719..8b69e7ed 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -368,19 +368,13 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->code = dest; proc->code_size = code_size; - proc->main_thread.spsr = 0; - uint64_t shared_pages = 1; size_t shared_size = shared_pages * PAGE_SIZE; - stack_t main_stack = new_stack(proc); - if (!main_stack.top || !main_stack.size){ - reset_process(proc); - return 0; - } + new_thread(proc, &proc->main_thread, 0, entry); - uaddr_t stack_top = main_stack.top; - uaddr_t stack_limit = stack_top - main_stack.max; + uaddr_t stack_top = proc->main_thread.stack_info.top; + uaddr_t stack_limit = stack_top - proc->main_thread.stack_info.max; uaddr_t stack_commit = stack_top; uaddr_t mmap_top = stack_min_addr - PAGE_SIZE; uaddr_t shared_base = mmap_top - (shared_size - PAGE_SIZE); @@ -408,15 +402,10 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat for (uint64_t i = 0; i < shared_pages; i++) mmu_map_4kb((uint64_t*)ttbr, (uint64_t)(shared_base + (i * PAGE_SIZE)), (paddr_t)(shared_page + (i * PAGE_SIZE)), MAIR_IDX_NORMAL, MEM_EXEC | MEM_NORM, MEM_PRIV_SHARED); mm_add_vma(&proc->mm, shared_base, shared_base + shared_size, MEM_EXEC | MEM_NORM, VMA_KIND_SPECIAL, VMA_FLAG_NOFREE); - - proc->main_thread.stack = stack_top; - proc->main_thread.stack_size = main_stack.size; + proc->mm.rss_stack_pages = 0; - proc->main_thread.sp = proc->main_thread.stack; - - proc->main_thread.pc = (uintptr_t)(entry); - proc->main_thread.regs[30] = shared_base; + proc->shared_page = shared_base; kprintf("[NEW PROC:U]: %s (pid: %i, main tid: %i) allocated at %llx entry=%llx stack=%llx-%llx anon=%llx (phys=%llx)", name, proc->id, proc->main_thread.tid, proc, (uint64_t)proc->main_thread.pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); proc->state = BLOCKED; diff --git a/kernel/process/process.h b/kernel/process/process.h index d5a0d260..5efd41bf 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -71,6 +71,7 @@ typedef struct thread { //Not used in context saving uintptr_t stack; uint64_t stack_size; + stack_t stack_info; u16 pid; u16 tid; process_state thread_state; @@ -100,6 +101,7 @@ typedef struct process { page_index *alloc_map; draw_ctx graphics_ctx; process_state state; + u64 spsr; __attribute__((aligned(16))) input_buffer_t input_buffer; __attribute__((aligned(16))) event_buffer_t event_buffer; __attribute__((aligned(16))) packet_buffer_t packet_buffer; @@ -127,7 +129,7 @@ typedef struct process { } process_t; static inline bool is_privileged(process_t *proc){ - return proc->main_thread.spsr & 0xf; + return proc->spsr & 0xf; } //Helper functions for accessing registers mapped to scratch regs diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 50fcca24..5910f8c4 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -245,6 +245,8 @@ void ready_process(process_t *proc){ return; } + proc->spsr = proc->main_thread.spsr;//TODO: remove + enqueue_ready_process(proc); irq_restore(irq); } @@ -275,6 +277,8 @@ void reset_process(process_t *proc){ proc->pending_reset = false; proc->sleeping = false; proc->wake_at_msec = 0; + proc->thread_count = 0;//TODO: clean up all threads + proc->thread_ids = 0; remove_sleeping_process(proc, pid); @@ -470,19 +474,15 @@ void init_main_process(){ kernel_proc->id = next_proc_index++; kernel_proc->alloc_map = make_page_index(); kernel_proc->state = BLOCKED; - kernel_proc->main_thread.spsr = 0x205; - kernel_proc->main_thread.sp = (uintptr_t)ksp; + + new_thread(kernel_proc, &kernel_proc->main_thread, 0x205, 0); + kernel_proc->priority = PROC_PRIORITY_LOW; name_process(kernel_proc, "kernel"); idle_proc->state = BLOCKED; idle_proc->priority = PROC_PRIORITY_LOW; - idle_proc->main_thread.stack_size = 0x4000; - uintptr_t idle_stack = (uintptr_t)palloc(idle_proc->main_thread.stack_size,MEM_PRIV_KERNEL, MEM_RW,true); - if (!idle_stack) panic("idle stack alloc failed", 0); - idle_proc->main_thread.stack = idle_stack + idle_proc->main_thread.stack_size; - idle_proc->main_thread.sp = idle_proc->main_thread.stack; - idle_proc->main_thread.pc = (uintptr_t)idle_entry; - idle_proc->main_thread.spsr = 0x205; + + new_thread(idle_proc, &idle_proc->main_thread, 0x205, (uptr)idle_entry); name_process(idle_proc, "idle"); proc_count++; @@ -718,6 +718,8 @@ void schedule_thread(process_t *proc, thread_t *t){ } thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point){ + if (addr != &proc->main_thread) spsr = proc->spsr; + else proc->spsr = spsr; stack_t stack = new_stack(proc); if (!proc || !stack.top || !stack.size || !addr) return 0; *addr = (thread_t){ @@ -727,6 +729,7 @@ thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point .sp = stack.top, .stack_size = stack.size, .stack = stack.top, + .stack_info = stack, .spsr = spsr, .tid = ++proc->thread_ids // .state = BLOCKED, diff --git a/kernel/process/stack_manager.c b/kernel/process/stack_manager.c index cad76233..1d85f0a9 100644 --- a/kernel/process/stack_manager.c +++ b/kernel/process/stack_manager.c @@ -14,7 +14,12 @@ uptr next_stack_addr(process_t *proc){ } stack_t new_stack(process_t *proc){ - uptr stack_top = is_privileged(proc) ? (uptr)palloc(stack_max, MEM_PRIV_KERNEL, MEM_RW, true) : next_stack_addr(proc); + uptr stack_top = 0; + if (is_privileged(proc)) { + void *st = palloc(stack_max, MEM_PRIV_KERNEL, MEM_RW, true); + stack_top = (uptr)st; + register_allocation(proc->alloc_map, st, stack_max); + } else stack_top = next_stack_addr(proc); if (!stack_top) return (stack_t){}; uptr stack_limit = stack_top - stack_max; print("New stack at %llx-%llx",stack_limit,stack_top); From 627720dfa944ac5cfdafe272cbd01659aa38a63e Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Tue, 30 Jun 2026 00:00:00 +0000 Subject: [PATCH 16/65] [PROC] removed redundant stack info [PROC] removed signal buffer --- kernel/kernel_processes/kprocess_loader.c | 4 ++-- kernel/process/loading/elf_file.c | 8 ++++---- kernel/process/process.h | 3 --- kernel/process/scheduler.c | 9 +++------ kernel/tools/monitor_processes.c | 4 ++-- 5 files changed, 11 insertions(+), 17 deletions(-) diff --git a/kernel/kernel_processes/kprocess_loader.c b/kernel/kernel_processes/kprocess_loader.c index 1595c1ce..3d01e78e 100644 --- a/kernel/kernel_processes/kprocess_loader.c +++ b/kernel/kernel_processes/kprocess_loader.c @@ -65,7 +65,7 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a if (need + 0x20 < proc->main_thread.stack_info.size) { - uintptr_t top = proc->main_thread.stack; + uintptr_t top = proc->main_thread.stack_info.top; uintptr_t base = (top - need) & ~0xFULL; char **kargv = (char**)base; @@ -98,7 +98,7 @@ process_t *create_kernel_process(const char *name, int (*func)(int argc, char* a make_process_fs(proc, 0); ready_process(proc); - kprintf("[NEW PROC:K] process %s (pid: %i main tid: %i) allocated with address at %llx, stack at %llx-%llx, heap at %llx. %i argument(s)", (uintptr_t)name, proc->id, proc->main_thread.tid, proc->main_thread.pc, proc->main_thread.sp - proc->main_thread.stack_size, proc->main_thread.sp, (uaddr_t)dmap_pa_to_kva(proc->heap_phys), argc); + kprintf("[NEW PROC:K] process %s (pid: %i main tid: %i) allocated with address at %llx, stack at %llx-%llx, heap at %llx. %i argument(s)", (uintptr_t)name, proc->id, proc->main_thread.tid, proc->main_thread.pc, proc->main_thread.sp - proc->main_thread.stack_info.size, proc->main_thread.sp, (uaddr_t)dmap_pa_to_kva(proc->heap_phys), argc); irq_restore(irq); return proc; diff --git a/kernel/process/loading/elf_file.c b/kernel/process/loading/elf_file.c index c3b8ff80..ad6e90b9 100644 --- a/kernel/process/loading/elf_file.c +++ b/kernel/process/loading/elf_file.c @@ -129,12 +129,12 @@ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { proc->main_thread.PROC_X0 = argc; proc->main_thread.PROC_X1 = 0; - proc->main_thread.sp = proc->main_thread.stack; + proc->main_thread.sp = proc->main_thread.stack_info.top; if (argc == 0) return true; if (!argv) return false; - size_t stack_size = proc->mm.ttbr0 ? (size_t)(proc->mm.stack_top - proc->mm.stack_limit) : proc->main_thread.stack_size; + size_t stack_size = proc->mm.ttbr0 ? (size_t)(proc->mm.stack_top - proc->mm.stack_limit) : proc->main_thread.stack_info.size; if (!stack_size) return false; size_t total_str = 0; @@ -150,7 +150,7 @@ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { if (argv_size > stack_size) return false; if (total_str > stack_size - argv_size) return false; - uintptr_t str_base = proc->main_thread.stack - total_str; + uintptr_t str_base = proc->main_thread.stack_info.top - total_str; if (argc > UACCESS_MAX_ARGV) return false; uintptr_t arg_ptrs[UACCESS_MAX_ARGV + 1] = {}; uintptr_t sp = str_base & ~0xFULL; @@ -173,7 +173,7 @@ bool setup_process_args(process_t *proc, int argc, const char *argv[]) { return true; } - paddr_t str_phys = proc->main_thread.stack - total_str; + paddr_t str_phys = proc->main_thread.stack_info.top - total_str; size_t off = 0; for (int i = 0; i < argc; i++) { size_t len = strlen(argv[i]); diff --git a/kernel/process/process.h b/kernel/process/process.h index 5efd41bf..4de695da 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -69,8 +69,6 @@ typedef struct thread { uintptr_t pc; uint64_t spsr; //Not used in context saving - uintptr_t stack; - uint64_t stack_size; stack_t stack_info; u16 pid; u16 tid; @@ -106,7 +104,6 @@ typedef struct process { __attribute__((aligned(16))) event_buffer_t event_buffer; __attribute__((aligned(16))) packet_buffer_t packet_buffer; __attribute__((aligned(16))) scroll_buffer_t scroll_buffer; - __attribute__((aligned(16))) signal_buffer_t signal_buffer; __attribute__((aligned(16))) thread_t signal_handlers[NUMBER_SIGNALS]; uint8_t priority; system_permissions permissions; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 5910f8c4..bee138cd 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -72,7 +72,7 @@ bool process_is_known(process_t *proc){ } bool process_has_runtime_state(process_t *proc){ - return proc && (proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); + return proc && (proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack_info.size || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); } bool process_can_run(process_t *proc){ @@ -271,7 +271,7 @@ void reset_process(process_t *proc){ uint16_t pid = proc->id; int32_t exit_code = proc->exit_code; - bool counted = proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack || proc->heap_phys || proc->mm.ttbr0; + bool counted = proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack_info.size || proc->heap_phys || proc->mm.ttbr0; irq_flags_t irq = irq_save_disable(); proc->pending_reset = false; @@ -435,8 +435,7 @@ void reset_process(process_t *proc){ memset(proc->name, 0, sizeof(proc->name)); - proc->main_thread.stack = 0; - proc->main_thread.stack_size = 0; + proc->main_thread.stack_info = (stack_t){}; proc->heap_phys = 0; memset(&proc->mm, 0, sizeof(proc->mm)); @@ -727,8 +726,6 @@ thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point .pid = proc->id, .regs = {}, .sp = stack.top, - .stack_size = stack.size, - .stack = stack.top, .stack_info = stack, .spsr = spsr, .tid = ++proc->thread_ids diff --git a/kernel/tools/monitor_processes.c b/kernel/tools/monitor_processes.c index fec1e2a0..24dee29a 100644 --- a/kernel/tools/monitor_processes.c +++ b/kernel/tools/monitor_processes.c @@ -45,7 +45,7 @@ void print_process_info(){ while (proc){ if (proc->id != 0 && proc->state != STOPPED && (!procname || strcmp_case(procname,proc->name,true) == 0)){ print("Process %s [pid = %i | status = %s]",(uintptr_t)proc->name,proc->id,(uintptr_t)parse_proc_state(proc->state)); - print("Stack: %x (%x). SP: %x",proc->main_thread.stack, proc->main_thread.stack_size, proc->main_thread.sp); + print("Stack: %x (%x). SP: %x",proc->main_thread.stack_info.top, proc->main_thread.stack_info.size, proc->main_thread.sp); print("Heap: %x (%x)",proc->mm.mmap_bottom, calc_heap(proc->heap_phys)); print("Flags: %x", proc->main_thread.spsr); print("PC: %x",proc->main_thread.pc); @@ -130,7 +130,7 @@ void draw_process_view(){ fb_draw_string(&ctx,pc.data, xo, pc_y, scale, system_theme.bg_color); string_free(pc); - draw_memory("Stack", xo, stack_y, stack_width, stack_height, proc->main_thread.stack - proc->main_thread.sp, proc->main_thread.stack_size ? proc->main_thread.stack_size : 1); + draw_memory("Stack", xo, stack_y, stack_width, stack_height, proc->main_thread.stack_info.top - proc->main_thread.sp, proc->main_thread.stack_info.size ? proc->main_thread.stack_info.size : 1); uint64_t heap = proc->mm.ttbr0 ? (proc->mm.rss_anon_pages * PAGE_SIZE) : calc_heap(proc->heap_phys); uint64_t heap_limit = proc->mm.ttbr0 ? (uint64_t)(proc->mm.mmap_top - proc->mm.mmap_bottom) : ((heap + 0xFFF) & ~0xFFF); draw_memory("Heap", xo + stack_width + 50, stack_y, stack_width, stack_height, heap, heap_limit ? heap_limit : PAGE_SIZE); From b218a93479e790e4d317a4043a98b824e002b42a Mon Sep 17 00:00:00 2001 From: di Date: Fri, 3 Jul 2026 00:00:00 +0000 Subject: [PATCH 17/65] [THREADING, WIP] job system (no memory sharing between procs yet) --- kernel/filesystem/filesystem.c | 22 ++++++++-- kernel/process/jobs/job_manager.c | 70 +++++++++++++++++++++++++++++++ kernel/process/jobs/job_manager.h | 7 ++++ kernel/process/process.h | 4 +- kernel/process/scheduler.c | 10 +++++ kernel/process/scheduler.h | 4 +- kernel/process/syscall.c | 4 ++ shared | 2 +- user/terminal/main.c | 7 +++- 9 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 kernel/process/jobs/job_manager.c create mode 100644 kernel/process/jobs/job_manager.h diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index fea6e2fb..e9918539 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -6,6 +6,7 @@ #include "process/scheduler.h" #include "pipe.h" #include "files/dir_list.h" +#include "process/jobs/job_manager.h" uint64_t fd_id = 256;//First byte reserved @@ -259,10 +260,23 @@ bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ } if (!mod->getstat) return false; if (mod->owner != get_kernel_proc()->id){ - kprintf("cba rn"); - return false; - } else - return mod->getstat(search_path, out_stat); + if (get_current_proc()->id == mod->owner){ + //TODO: We can probably optimize this more, but right now it blocks the entire process so we can't allow this case + return false; + } + process_t *owner_proc = get_proc_by_pid(mod->owner); + if (!is_privileged(owner_proc)){ + create_new_job((job_application_t){ + .requesting_pid = get_current_proc()->id, + .requesting_tid = get_current_proc()->current_thread->tid, + .worker_pid = owner_proc->id, + .type = job_stat + }); + + return false; + } + } + return mod->getstat(search_path, out_stat); } bool truncate(file *descriptor, size_t size){ diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c new file mode 100644 index 00000000..8acbe091 --- /dev/null +++ b/kernel/process/jobs/job_manager.c @@ -0,0 +1,70 @@ +#include "job_manager.h" +#include "process/process.h" +#include "process/scheduler.h" +#include "data/struct/linked_list.h" + +job_id_t job_id_counter = 1; + +typedef struct { + thread_t *requester; + thread_t *worker; + job_id_t id; +} job_state_t; + +linked_list_t *job_list; + +void *job_page; + +void* job_man_alloc(size_t size){ + return allocate(job_page, size, page_alloc); +} + +job_state_t* job_alloc(){ + if (!job_page) job_page = page_alloc(PAGE_SIZE); + if (!job_list) job_list = linked_list_create_alloc(job_man_alloc, release); + job_state_t *job = job_man_alloc(sizeof(job_state_t)); + job->id = job_id_counter++; + linked_list_push(job_list, job); + return job; +} + +job_id_t create_new_job(job_application_t application){ + job_state_t *job = job_alloc(); + process_t *requesting_proc = get_proc_by_pid(application.requesting_pid); + if (!requesting_proc){ + print("[JOB error] Unknown requesting proc %i",application.requesting_pid); + } + thread_t *requester = (thread_t*)get_thread_from_proc(requesting_proc, application.requesting_tid); + job->requester = requester; + process_t *fs_owner = get_proc_by_pid(application.worker_pid); + print("[JOB DEBUG] Sync between %i - %i will happen with job %i",requester->pid,application.worker_pid,job->id); + thread_t *new_t = alloc_thread(); + new_thread(fs_owner, new_t, fs_owner->spsr, (uptr)fs_owner->exposed_fs.getstat); + new_t->job_id = job->id; + job->worker = new_t; + requester->thread_state = BLOCKED; + schedule_thread(fs_owner, new_t); + return job->id; +} + +job_state_t* get_job_state(job_id_t job_id){ + for (linked_list_node_t *cur = job_list->head; cur && cur->data; cur = cur->next){ + job_state_t *job = cur->data; + if (job->id == job_id) return job; + } + return 0; +} + +void fulfill_job(job_id_t job_id, thread_t *thread){ + job_state_t *st = get_job_state(job_id); + if (!st) { + print("[JOB error] Could not find id %i",job_id); + return; + } + if (thread->job_id != job_id || st->worker != thread){ + print("[JOB error] termination request by wrong thread %i",thread->tid); + return; + } + st->requester->thread_state = READY;//TODO: schedule once the scheduler is fully thread-based + print("[JOB] %i fulfilled",job_id); +} \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h new file mode 100644 index 00000000..3f11d16a --- /dev/null +++ b/kernel/process/jobs/job_manager.h @@ -0,0 +1,7 @@ +#pragma once + +#include "files/jobs.h" +#include "process/process.h" + +job_id_t create_new_job(job_application_t application); +void fulfill_job(job_id_t job_id, thread_t *thread); diff --git a/kernel/process/process.h b/kernel/process/process.h index 4de695da..1799349c 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -12,6 +12,7 @@ extern "C" { #include "graphic_types.h" #include "signals/signals.h" #include "environment/environment.h" +#include "files/jobs.h" #define INPUT_BUFFER_CAPACITY 64 #define PACKET_BUFFER_CAPACITY 128 @@ -74,6 +75,7 @@ typedef struct thread { u16 tid; process_state thread_state; struct thread *next; + job_id_t job_id; } thread_t; typedef struct process { @@ -143,4 +145,4 @@ static inline bool is_privileged(process_t *proc){ #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index bee138cd..98b290fe 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -260,6 +260,16 @@ process_t* get_proc_by_pid(uint16_t pid){ return NULL; } +thread_t* get_thread_from_proc(process_t *proc, u16 tid){ + if (proc->current_thread->tid == tid) return proc->current_thread; + thread_t *t = &proc->main_thread; + do { + if (t->tid == tid) return t; + t = t->next; + } while (t); + return 0; +} + uint16_t get_current_proc_pid(){ return current_proc ? current_proc->id : 0; } diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 384892fb..067166a0 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -67,8 +67,8 @@ thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point void unschedule_thread(process_t *proc, thread_t *t); void schedule_thread(process_t *proc, thread_t *t); -bool init_scheduler(); +thread_t* get_thread_from_proc(process_t *proc, u16 tid); -u64 run_thread_oneshot(thread_t *t, process_t *p); +bool init_scheduler(); extern char ksp[]; diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 3a8d3932..58b11a64 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -34,6 +34,7 @@ #include "filesystem/modules/fs_isolation.h" #include "files/dir_list.h" #include "theme/theme.h" +#include "jobs/job_manager.h" int syscall_depth = 0; uintptr_t cpec; @@ -192,6 +193,9 @@ u64 syscall_halt(process_t *ctx, thread_t *current_thread){ u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ kprintf("Thread has ended with code %i",current_thread->PROC_X0); syscall_depth--; + if (current_thread->job_id){ + fulfill_job(current_thread->job_id, current_thread); + } if (current_thread == &ctx->main_thread) stop_current_process(current_thread->PROC_X0); else { diff --git a/shared b/shared index af6f33f2..ad396a2d 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit af6f33f22d03d504513065647d6f8038b578e936 +Subproject commit ad396a2d2f189b25cbc6b0613203e7558db7d54f diff --git a/user/terminal/main.c b/user/terminal/main.c index c91059a4..f3aefe83 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -283,6 +283,11 @@ bool termhistory_init(system_module *mod){ return true; } +bool custom_stat(const char *path, fs_stat *out_stat){ + print("Hello"); + return true; +} + system_module termhistory_mod = { .name = "terminal history", .mount = "termhistory", @@ -292,7 +297,7 @@ system_module termhistory_mod = { .read = stackfs_read, .write = stackfs_write, .readdir = stackfs_readdir, - .getstat = stackfs_stat + .getstat = custom_stat }; int main(){ From af76310556b5aaf582127e24aea78ee71a1aa2b5 Mon Sep 17 00:00:00 2001 From: di Date: Sat, 4 Jul 2026 00:00:00 +0000 Subject: [PATCH 18/65] [JOB] copying buffers into worker --- kernel/filesystem/filesystem.c | 8 +- kernel/process/jobs/job_manager.c | 39 ++- kernel/process/jobs/job_manager.h | 23 ++ shared | 2 +- user/terminal/main.c | 3 +- user/terminal/main.cpp | 53 ---- user/terminal/terminal.cpp | 392 ------------------------------ user/terminal/terminal.hpp | 59 ----- 8 files changed, 69 insertions(+), 510 deletions(-) delete mode 100644 user/terminal/main.cpp delete mode 100644 user/terminal/terminal.cpp delete mode 100644 user/terminal/terminal.hpp diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index e9918539..e33b03ab 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -266,13 +266,15 @@ bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ } process_t *owner_proc = get_proc_by_pid(mod->owner); if (!is_privileged(owner_proc)){ - create_new_job((job_application_t){ + job_application_t app = (job_application_t){ .requesting_pid = get_current_proc()->id, .requesting_tid = get_current_proc()->current_thread->tid, .worker_pid = owner_proc->id, .type = job_stat - }); - + }; + job_serialize_str(&app, 0, search_path); + job_serialize_stat(&app, 1, out_stat); + create_new_job(app); return false; } } diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 8acbe091..c06d7e18 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -2,6 +2,9 @@ #include "process/process.h" #include "process/scheduler.h" #include "data/struct/linked_list.h" +#include "memory/mmu.h" +#include "memory/addr.h" +#include "memory/memory.h" job_id_t job_id_counter = 1; @@ -28,6 +31,40 @@ job_state_t* job_alloc(){ return job; } +bool prepare_thread(job_application_t application, process_t *proc, thread_t *t){ + uptr entry = 0; + switch (application.type){ + case job_stat: entry = (uptr)proc->exposed_fs.getstat; break; + default: return false; + } + if (!entry) return false; + new_thread(proc, t, proc->spsr, (uptr)proc->exposed_fs.getstat); + size_t total_size = 0; + for (size_t i = 0; i < application.buffer_count; i++) + total_size += application.buffers[i].ptr.size; + size_t num_pages = count_pages(total_size, PAGE_SIZE); + uptr buffers = mm_alloc_mmap(&proc->mm, total_size, MEM_RW, VMA_KIND_SPECIAL, 0); + uptr pbuffers = (uptr)palloc_inner(total_size, MEM_PRIV_SHARED, MEM_RW, true, false); + for (size_t i = 0; i < num_pages; i++){ + mmu_map_4kb(proc->mm.ttbr0, buffers + (i * PAGE_SIZE), pbuffers + (i * PAGE_SIZE), MAIR_IDX_NORMAL, MEM_RW, MEM_PRIV_USER); + register_proc_memory(PHYS_TO_VIRT(pbuffers + (i * PAGE_SIZE)), pbuffers + (i * PAGE_SIZE), MEM_RW, MEM_PRIV_KERNEL); + } + print("Our buffers will go to %llx - %llx",buffers,pbuffers); + uptr next_addr_pa = PHYS_TO_VIRT(pbuffers); + uptr next_addr_va = buffers; + + for (size_t i = 0; i < application.buffer_count; i++){ + job_buffer buf = application.buffers[i]; + memcpy((void*)next_addr_pa, (void*)buf.ptr.ptr, buf.ptr.size); + t->regs[buf.arg_num] = next_addr_va; + if (buf.explicit_size) + t->regs[buf.arg_num+1] = buf.ptr.size; + next_addr_pa += buf.ptr.size; + next_addr_va += buf.ptr.size; + } + return true; +} + job_id_t create_new_job(job_application_t application){ job_state_t *job = job_alloc(); process_t *requesting_proc = get_proc_by_pid(application.requesting_pid); @@ -39,7 +76,7 @@ job_id_t create_new_job(job_application_t application){ process_t *fs_owner = get_proc_by_pid(application.worker_pid); print("[JOB DEBUG] Sync between %i - %i will happen with job %i",requester->pid,application.worker_pid,job->id); thread_t *new_t = alloc_thread(); - new_thread(fs_owner, new_t, fs_owner->spsr, (uptr)fs_owner->exposed_fs.getstat); + if (!prepare_thread(application, fs_owner, new_t)) return false; new_t->job_id = job->id; job->worker = new_t; requester->thread_state = BLOCKED; diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index 3f11d16a..9d294c54 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -3,5 +3,28 @@ #include "files/jobs.h" #include "process/process.h" +static inline void job_application_append_buffer(job_application_t *app, job_buffer buf){ + if (app->buffer_count >= MAX_JOB_BUFFERS) return; + app->buffers[app->buffer_count++] = buf; +} + +static inline void job_serialize_str(job_application_t *application, u8 arg_num, const char *str){ + job_buffer buf = { + .ptr = {.ptr = (uptr)str, .size = strlen(str)+1}, + .arg_num = arg_num, + .explicit_size = false + }; + job_application_append_buffer(application, buf); +} + +static inline void job_serialize_stat(job_application_t *application, int arg_num, fs_stat *stat){ + job_buffer buf = { + .ptr = {.ptr = (uptr)stat, .size = sizeof(fs_stat)}, + .arg_num = arg_num, + .explicit_size = false + }; + job_application_append_buffer(application, buf); +} + job_id_t create_new_job(job_application_t application); void fulfill_job(job_id_t job_id, thread_t *thread); diff --git a/shared b/shared index ad396a2d..4cf55157 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit ad396a2d2f189b25cbc6b0613203e7558db7d54f +Subproject commit 4cf5515704e3da9a30f7a381a791c58ce26c7a62 diff --git a/user/terminal/main.c b/user/terminal/main.c index f3aefe83..3857767b 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -284,7 +284,8 @@ bool termhistory_init(system_module *mod){ } bool custom_stat(const char *path, fs_stat *out_stat){ - print("Hello"); + print("Stat %s into %x",path, out_stat); + stat_dir(out_stat); return true; } diff --git a/user/terminal/main.cpp b/user/terminal/main.cpp deleted file mode 100644 index f7c04074..00000000 --- a/user/terminal/main.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "terminal.hpp" -#include "string/string.h" - -Terminal *term; - -int main(int argc, char **argv){ - term = new Terminal(); - if (argc && strncmp_case(argv[0], "headless", true, 8) == 0){ - print("Terminal in headless mode"); - term->headless = true; - } - while (1){ - term->update(); - } -} - -void term_put_char(shell_handle *handle, char c){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - if (term->headless && c) - serial_transmit(c); - else - term->put_char(c); -} - -void term_clear(shell_handle *handle){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->clear(); -} - -void term_flush(shell_handle *handle){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->refresh(); -} - -void term_bell(shell_handle *handle){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->bell(); -} - -void term_ascii_cmd(shell_handle *handle, char cmd, u16 proc_id){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->interpret_cmd_code(cmd, proc_id); -} - -void term_console_ctrl(shell_handle *handle, console_ctrls ctrl){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->ctrl(ctrl); -} - -void term_emit_data(structdef field, sizedptr data, bool is_allocated){ - if (!term) return; - term->emit_data(field,data,is_allocated); -} \ No newline at end of file diff --git a/user/terminal/terminal.cpp b/user/terminal/terminal.cpp deleted file mode 100644 index faa9d509..00000000 --- a/user/terminal/terminal.cpp +++ /dev/null @@ -1,392 +0,0 @@ -#include "terminal.hpp" -#include "alloc/allocate.h" -#include "memory/memory.h" -#include "input_keycodes.h" -#include "shell/sheldon/sheldon.h" -#include "data/serialize/binary_serial.h" -#include "utils/embedded_fmt/tcf.h" - -Terminal::Terminal() : Console() { - uint32_t color_buf[2] = {}; - sreadf("/theme", &color_buf, sizeof(uint64_t)); - if ((color_buf[0] & 0xFF000000) == 0) color_buf[0] |= 0xFF000000; - current_format.default_bg_color = color_buf[0]; - current_format.current_bg_color = color_buf[0]; - current_format.default_text_color = color_buf[1]; - - char_scale = 2; - prompt_length = 2; - command_running = false; - - input_len = 0; - input_cursor = 0; - input_buf[0] = 0; - - history_len = 0; - history_index = 0; - for (uint32_t i = 0; i < history_max; i++) history[i] = nullptr; - - last_blink_ms = get_time(); - cursor_visible = true; - - dirty = false; - - term_current_shell = create_shell(); - init_tcf(¤t_format); - put_string("> "); - redraw_input_line(); - if (dirty) { - flush(dctx); - dirty = false; - } -} - -extern void term_put_char(shell_handle *handle, char c); -extern void term_clear(shell_handle *handle); -extern void term_flush(shell_handle *handle); -extern void term_bell(shell_handle *handle); -extern void term_ascii_cmd(shell_handle *handle, char cmd, u16 proc_id); -extern void term_console_ctrl(shell_handle *handle, console_ctrls ctrl); - -shell_handle* Terminal::create_shell(){ - return create_sheldon(0); -} - -void Terminal::ctrl(console_ctrls ctrl){ - switch (ctrl) { - case console_ctrl_close: halt(0); - default: break; - } -} - -void Terminal::update(){ - if (!command_running) { - bool did = handle_input(); - if (!did) cursor_tick(); - } else { - end_command(); - } - - if (dirty) { - flush(dctx); - dirty = false; - } -} - -void Terminal::cursor_set_visible(bool visible){ - if (visible == cursor_visible) { - if (!visible) return; - if (last_drawn_cursor_x == (int32_t)current_format.cursor_x && last_drawn_cursor_y == (int32_t)current_format.cursor_y) return; - } - - cursor_visible = visible; - - if (last_drawn_cursor_x >= 0 && last_drawn_cursor_y >= 0) { - if ((uint32_t)last_drawn_cursor_x < columns && (uint32_t)last_drawn_cursor_y < rows) { - char *prev_line = &row_data[((scroll_row_offset + (u32)last_drawn_cursor_y) % rows) * columns]; - render_glyph(last_drawn_cursor_x*char_width, last_drawn_cursor_y * line_height, prev_line[last_drawn_cursor_x], current_format.current_text_color, current_format.current_bg_color, true); - } - last_drawn_cursor_x = -1; - last_drawn_cursor_y = -1; - } - - if (cursor_visible) { - fb_fill_rect(dctx, current_format.cursor_x * char_width, current_format.cursor_y * line_height, char_width, line_height, 0xFFFFFFFF); - last_drawn_cursor_x = (int32_t)current_format.cursor_x; - last_drawn_cursor_y = (int32_t)current_format.cursor_y; - } - - dirty = true; -} - -void Terminal::cursor_tick(){ - uint64_t now = get_time(); - if ((now - last_blink_ms) < 500) return; - last_blink_ms = now; - cursor_set_visible(!cursor_visible); -} - -void Terminal::redraw_input_line(){ - if (!check_ready()) return; - - uint32_t cw = (uint32_t)char_scale * CHAR_SIZE; - uint32_t lh = (uint32_t)char_scale * CHAR_SIZE * 2; - - fb_fill_rect(dctx, 0, current_format.cursor_y * lh, columns * cw, lh, current_format.current_bg_color); - - char* line = row_data + (((scroll_row_offset + current_format.cursor_y) % rows) * columns); - memset(line, 0, columns); - - if (columns == 0) return; - if (prompt_length >= (int)columns) return; - - line[0] = '>'; - line[1] = ' '; - - uint32_t max_input = columns - (uint32_t)prompt_length - 1; - uint32_t draw_len = input_len; - if (draw_len > max_input) draw_len = max_input; - - for (uint32_t i = 0; i < draw_len; i++) line[prompt_length + i] = input_buf[i]; - line[prompt_length + draw_len] = 0; - - uint32_t ypix = (current_format.cursor_y * lh) + (lh / 2); - fb_draw_char(dctx, 0, ypix, '>', char_scale, current_format.current_text_color); - fb_draw_char(dctx, cw, ypix, ' ', char_scale, current_format.current_text_color); - for (uint32_t i = 0; i < draw_len; i++) fb_draw_char(dctx, (prompt_length + i) * cw, ypix, input_buf[i], char_scale, current_format.current_text_color); - - if (input_cursor > draw_len) input_cursor = draw_len; - current_format.cursor_x = (uint32_t)prompt_length + input_cursor; - - last_blink_ms = get_time(); - cursor_set_visible(true); -} - -void Terminal::set_input_line(const char *s){ - input_len = 0; - input_cursor = 0; - - if (s) { - uint32_t i = 0; - while (s[i] && (i + 1) < input_max) { - input_buf[i] = s[i]; - i++; - } - input_len = i; - } - - input_buf[input_len] = 0; - input_cursor = input_len; - redraw_input_line(); -} - -void Terminal::end_command(){ - command_running = false; - if (last_char != '\r' && last_char != '\n'){ - put_char('\r'); - put_char('\n'); - } - put_string("> "); - prompt_length = 2; - - set_input_line(""); -} - -void Terminal::emit_data(structdef field, sizedptr data, bool is_allocated){ - if (!data.ptr || !data.size) return; - switch (field.type) { - case binary_type_i8: print("%S: %i",field.name,*(i8*)data.ptr); break; - case binary_type_i16: print("%S: %i",field.name,*(i16*)data.ptr); break; - case binary_type_i32: print("%S: %i",field.name,*(i32*)data.ptr); break; - case binary_type_i64: print("%S: %i",field.name,*(i64*)data.ptr); break; - case binary_type_float: print("%S: %f",field.name,*(float*)data.ptr); break; - case binary_type_double: print("%S: %f",field.name,*(double*)data.ptr); break; - case binary_type_string: print("%S: %v",field.name,data); break; - default: return; - } - if (is_allocated) release((void*)data.ptr); -} - -bool Terminal::exec_cmd(const char *cmd){ - if (!term_current_shell) return false; - - current_shell = term_current_shell; - - if (run_cmd(current_shell, slice_from_literal(cmd))) return true; - - return true; -} - -void Terminal::bell(){ - put_string("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - refresh(); -} - -void Terminal::run_command(){ - if (input_len) { - if (history_len == history_max) { - if (history[0]) release(history[0]); - for (uint32_t i = 1; i < history_max; i++) history[i - 1] = history[i]; - history_len = history_max - 1; - } - - uint32_t n = input_len; - char *copy = (char*)zalloc(n + 1); - if (copy) { - memcpy(copy, input_buf, n); - copy[n] = 0; - history[history_len++] = copy; - } - } - history_index = history_len; - - put_char('\r'); - put_char('\n'); - - const char* fullcmd = input_buf; - while (*fullcmd == ' ' || *fullcmd == '\t') fullcmd++; - - if (*fullcmd == 0) { - command_running = true; - return; - } - - if (!exec_cmd(fullcmd)){ - const char *next = seek_to(fullcmd, ' '); - size_t len = next - fullcmd - (next && *(next-1) == ' ' ? 1 : 0); - string_slice cmd = (string_slice){ .data = (char*)fullcmd, .length = len }; - if (slice_lit_match(cmd, "exit", true) || slice_lit_match(cmd, "q", true)){ - halt(0); - } else { - string s = string_format("Unknown command %v", cmd); - put_string(s.data); - string_free(s); - } - } - - command_running = true; -} - -bool Terminal::interpret_cmd_code(char code, u16 proc){ - if (code == ASCII_CMD_ETX){ - send_signal(SIG_QUIT, proc); - return true; - } - if (code == ASCII_CMD_SUB){ - send_signal(SIG_STOP, proc); - return true; - } - if (code == ASCII_CMD_CAN){ - send_signal(SIG_CONT, proc); - } - return false; -} - -bool Terminal::handle_input(){ - kbd_event event; - if (!read_event(&event)) return false; - if (event.type == KEY_RELEASE) return true; - if (event.type != KEY_PRESS) return handle_modifier(&event); - - char key = event.key; - char readable = hid_to_char((uint8_t)key, current_modifier, special_key); - - if (command_running){ - return interpret_cmd_code(readable, 0); - } - - if (key == KEY_ENTER || key == KEY_KPENTER){ - run_command(); - return true; - } - - if (key == KEY_LEFT) { - if (input_cursor) input_cursor--; - current_format.cursor_x = (uint32_t)prompt_length + input_cursor; - last_blink_ms = get_time(); - cursor_set_visible(true); - return true; - } - - if (key == KEY_RIGHT) { - if (input_cursor < input_len) input_cursor++; - current_format.cursor_x = (uint32_t)prompt_length + input_cursor; - last_blink_ms = get_time(); - cursor_set_visible(true); - return true; - } - - if (key == KEY_UP) { - if (history_len && history_index) { - history_index--; - set_input_line(history[history_index]); - } - return true; - } - - if (key == KEY_DOWN) { - if (history_len) { - if (history_index + 1 < history_len) { - history_index++; - set_input_line(history[history_index]); - } else { - history_index = history_len; - set_input_line(""); - } - } - return true; - } - - if (key == KEY_BACKSPACE){ - if (!input_cursor) return true; - for (uint32_t i = input_cursor; i < input_len; i++) input_buf[i - 1] = input_buf[i]; - input_len--; - input_cursor--; - input_buf[input_len] = 0; - redraw_input_line(); - return true; - } - - if (key == KEY_DELETE) { - if (input_cursor >= input_len) return true; - for (uint32_t i = input_cursor + 1; i <= input_len; i++) input_buf[i - 1] = input_buf[i]; - input_len--; - redraw_input_line(); - return true; - } - - if (!readable) return true; - - uint32_t max_visible = 0; - if (columns > (uint32_t)prompt_length + 1) max_visible = columns - (uint32_t)prompt_length - 1; - if (input_len >= input_max - 1) return true; - if (max_visible && input_len >= max_visible) return true; - - for (uint32_t i = input_len; i > input_cursor; i--) input_buf[i] = input_buf[i - 1]; - input_buf[input_cursor] = readable; - input_len++; - input_cursor++; - input_buf[input_len] = 0; - redraw_input_line(); - return true; -} - -draw_ctx* Terminal::get_ctx(){ - if (dctx) release(dctx); - draw_ctx *ctx = (draw_ctx*)zalloc(sizeof(draw_ctx)); - if (!ctx) return nullptr; - request_draw_ctx(ctx); - return ctx; -} - -void Terminal::put_char(char c){ - if (headless){ - serial_transmit(c); - return; - } - Console::put_char(c); -} - -void Terminal::put_slice(string_slice slice){ - if (!check_ready()) return; - for (u32 i = 0; i < slice.length; i++) Terminal::put_char(slice.data[i]); - flush(dctx); -} - -void Terminal::put_string(const char* str){ - Terminal::put_slice(slice_from_literal(str)); -} - -void Terminal::flush(draw_ctx *ctx){ - if (headless) return; - commit_draw_ctx(ctx); -} - -void Terminal::refresh(){ - if (headless) return; - flush(dctx); -} - -bool Terminal::screen_ready(){ - return !headless; -} diff --git a/user/terminal/terminal.hpp b/user/terminal/terminal.hpp deleted file mode 100644 index a0f6cd86..00000000 --- a/user/terminal/terminal.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "utils/console.hpp" -#include "shell/shell.h" -#include "kbd_helper.h" -#include "environment/env_types.h" -#include "data/serialize/binary_serial.h" - -class Terminal: public Console { -public: - Terminal(); - void update(); - shell_handle *term_current_shell; - void emit_data(structdef, sizedptr, bool); - void refresh(); - void bell(); - bool interpret_cmd_code(char code, u16 proc); - void ctrl(console_ctrls ctrl); - void put_char(char c) override; - void put_string(const char* str) override; - void put_slice(string_slice slice) override; - bool headless; -protected: - bool handle_input(); - void repeat_tick(); - void end_command(); - int prompt_length; - void run_command(); - - void redraw_input_line(); - void set_input_line(const char *s); - void cursor_tick(); - void cursor_set_visible(bool visible); - - bool exec_cmd(const char *cmd); - - draw_ctx* get_ctx() override; - void flush(draw_ctx *ctx) override; - bool screen_ready() override; - - shell_handle* create_shell(); - - bool command_running; - - static constexpr uint32_t input_max = 1024; - char input_buf[input_max]; - uint32_t input_len; - uint32_t input_cursor; - - static constexpr uint32_t history_max = 32; - char *history[history_max]; - uint32_t history_len; - uint32_t history_index; - - uint64_t last_blink_ms; - bool cursor_visible; - - bool dirty; -}; \ No newline at end of file From 81864d7480824f3ac2d66f897fb7cd63b6c83415 Mon Sep 17 00:00:00 2001 From: di Date: Sat, 4 Jul 2026 00:00:00 +0000 Subject: [PATCH 19/65] [JOB] copy back [FS] readdir in userspace --- kernel/filesystem/filesystem.c | 23 ++++--------- kernel/process/jobs/job_manager.c | 51 ++++++++++++++++++++++------- kernel/process/jobs/job_manager.h | 54 ++++++++++++++++++++++++++++--- kernel/process/syscall.c | 2 +- shared | 2 +- user/terminal/main.c | 9 +++++- 6 files changed, 106 insertions(+), 35 deletions(-) diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index e33b03ab..c907d8a1 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -240,7 +240,11 @@ size_t list_directory_contents(module_root *root, const char *path, void* buf, s } if (!mod->readdir) return 0; if (mod->owner != get_kernel_proc()->id){ - kprintf("cba rn"); + job_make(job_readdir, { + job_serialize_str(&app, 0, search_path); + job_serialize_buf(&app, 1, true, buf, size, copy_on_end); + job_serialize_off(&app, 3, offset); + }); return 0; } else return mod->readdir(search_path, buf, size, offset); @@ -260,23 +264,10 @@ bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ } if (!mod->getstat) return false; if (mod->owner != get_kernel_proc()->id){ - if (get_current_proc()->id == mod->owner){ - //TODO: We can probably optimize this more, but right now it blocks the entire process so we can't allow this case - return false; - } - process_t *owner_proc = get_proc_by_pid(mod->owner); - if (!is_privileged(owner_proc)){ - job_application_t app = (job_application_t){ - .requesting_pid = get_current_proc()->id, - .requesting_tid = get_current_proc()->current_thread->tid, - .worker_pid = owner_proc->id, - .type = job_stat - }; + job_make(job_stat, { job_serialize_str(&app, 0, search_path); job_serialize_stat(&app, 1, out_stat); - create_new_job(app); - return false; - } + }) } return mod->getstat(search_path, out_stat); } diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index c06d7e18..73ff52e7 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -12,6 +12,8 @@ typedef struct { thread_t *requester; thread_t *worker; job_id_t id; + job_buffer buffers[8]; + size_t buffer_count; } job_state_t; linked_list_t *job_list; @@ -31,17 +33,18 @@ job_state_t* job_alloc(){ return job; } -bool prepare_thread(job_application_t application, process_t *proc, thread_t *t){ +bool prepare_thread(job_state_t *job, job_application_t application, process_t *proc, thread_t *t){ uptr entry = 0; switch (application.type){ case job_stat: entry = (uptr)proc->exposed_fs.getstat; break; + case job_readdir: entry = (uptr)proc->exposed_fs.readdir; break; default: return false; } if (!entry) return false; - new_thread(proc, t, proc->spsr, (uptr)proc->exposed_fs.getstat); + new_thread(proc, t, proc->spsr, entry); size_t total_size = 0; for (size_t i = 0; i < application.buffer_count; i++) - total_size += application.buffers[i].ptr.size; + total_size += application.buffers[i].worker_ptr.size; size_t num_pages = count_pages(total_size, PAGE_SIZE); uptr buffers = mm_alloc_mmap(&proc->mm, total_size, MEM_RW, VMA_KIND_SPECIAL, 0); uptr pbuffers = (uptr)palloc_inner(total_size, MEM_PRIV_SHARED, MEM_RW, true, false); @@ -49,18 +52,21 @@ bool prepare_thread(job_application_t application, process_t *proc, thread_t *t) mmu_map_4kb(proc->mm.ttbr0, buffers + (i * PAGE_SIZE), pbuffers + (i * PAGE_SIZE), MAIR_IDX_NORMAL, MEM_RW, MEM_PRIV_USER); register_proc_memory(PHYS_TO_VIRT(pbuffers + (i * PAGE_SIZE)), pbuffers + (i * PAGE_SIZE), MEM_RW, MEM_PRIV_KERNEL); } - print("Our buffers will go to %llx - %llx",buffers,pbuffers); + print("[JOB debug] buffers will go to %llx - %llx",buffers,pbuffers); uptr next_addr_pa = PHYS_TO_VIRT(pbuffers); uptr next_addr_va = buffers; for (size_t i = 0; i < application.buffer_count; i++){ job_buffer buf = application.buffers[i]; - memcpy((void*)next_addr_pa, (void*)buf.ptr.ptr, buf.ptr.size); + job->buffers[job->buffer_count++] = buf; + if (buf.sync == copy_on_start) + memcpy((void*)next_addr_pa, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); t->regs[buf.arg_num] = next_addr_va; + job->buffers[i].worker_ptr.ptr = next_addr_va; if (buf.explicit_size) - t->regs[buf.arg_num+1] = buf.ptr.size; - next_addr_pa += buf.ptr.size; - next_addr_va += buf.ptr.size; + t->regs[buf.arg_num+1] = buf.worker_ptr.size; + next_addr_pa += buf.worker_ptr.size; + next_addr_va += buf.worker_ptr.size; } return true; } @@ -74,12 +80,13 @@ job_id_t create_new_job(job_application_t application){ thread_t *requester = (thread_t*)get_thread_from_proc(requesting_proc, application.requesting_tid); job->requester = requester; process_t *fs_owner = get_proc_by_pid(application.worker_pid); - print("[JOB DEBUG] Sync between %i - %i will happen with job %i",requester->pid,application.worker_pid,job->id); + print("[JOB debug] Sync between %i - %i will happen with job %i - %i",requester->pid,application.worker_pid,job->id,application.type); thread_t *new_t = alloc_thread(); - if (!prepare_thread(application, fs_owner, new_t)) return false; + if (!prepare_thread(job, application, fs_owner, new_t)) return false; new_t->job_id = job->id; job->worker = new_t; requester->thread_state = BLOCKED; + requesting_proc->state = BLOCKED; schedule_thread(fs_owner, new_t); return job->id; } @@ -92,7 +99,7 @@ job_state_t* get_job_state(job_id_t job_id){ return 0; } -void fulfill_job(job_id_t job_id, thread_t *thread){ +void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ job_state_t *st = get_job_state(job_id); if (!st) { print("[JOB error] Could not find id %i",job_id); @@ -102,6 +109,26 @@ void fulfill_job(job_id_t job_id, thread_t *thread){ print("[JOB error] termination request by wrong thread %i",thread->tid); return; } - st->requester->thread_state = READY;//TODO: schedule once the scheduler is fully thread-based + st->requester->thread_state = RUNNING;//TODO: schedule once the scheduler is fully thread-based + process_t *proc = get_proc_by_pid(st->requester->pid); + proc->state = RUNNING;//TODO: this shouldn't be necessary + ready_process(proc); + st->requester->PROC_X0 = ret; + for (size_t i = 0; i < st->buffer_count; i++){ + job_buffer buf = st->buffers[i]; + if (buf.sync == copy_on_end){ + print("[JOB debug] Copy buffer %x into %x",buf.worker_ptr.ptr,buf.orig_ptr.ptr); + int status = 0; + uptr addr = mmu_translate(proc->mm.ttbr0, buf.orig_ptr.ptr, &status); + if (status){ + uint64_t esr = (0x24ULL << 26) | 0x7ULL; + if (!mm_try_handle_page_fault(proc, st->requester, buf.orig_ptr.ptr, esr)) return; + + addr = mmu_translate((uint64_t*)proc->mm.ttbr0, buf.orig_ptr.ptr, &status); + if (st) return; + } + memcpy((void*)PHYS_TO_VIRT(addr), (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); + } + } print("[JOB] %i fulfilled",job_id); } \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index 9d294c54..cc890636 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -3,28 +3,74 @@ #include "files/jobs.h" #include "process/process.h" +//TODO: We can probably optimize current proc fs more, but right now it blocks the entire process so we can't allow this case +#define job_make(job_type,action)\ +if (get_current_proc()->id == mod->owner){\ + return false;\ +}\ +process_t *owner_proc = get_proc_by_pid(mod->owner);\ +if (!is_privileged(owner_proc)){\ + job_application_t app = (job_application_t){\ + .requesting_pid = get_current_proc()->id,\ + .requesting_tid = get_current_proc()->current_thread->tid,\ + .worker_pid = owner_proc->id,\ + .type = job_type\ + };\ + action\ + create_new_job(app);\ + switch_proc(YIELD);\ + return false;\ +} + static inline void job_application_append_buffer(job_application_t *app, job_buffer buf){ if (app->buffer_count >= MAX_JOB_BUFFERS) return; app->buffers[app->buffer_count++] = buf; } static inline void job_serialize_str(job_application_t *application, u8 arg_num, const char *str){ + size_t size = strlen(str)+1; job_buffer buf = { - .ptr = {.ptr = (uptr)str, .size = strlen(str)+1}, + .worker_ptr = {.ptr = (uptr)str, .size = size}, + .orig_ptr = {.ptr = (uptr)str, .size = size}, + .sync = copy_on_start, .arg_num = arg_num, .explicit_size = false }; job_application_append_buffer(application, buf); } +static inline void job_serialize_buf(job_application_t *application, u8 arg_num, bool explicit_size, void *ptr, size_t size, job_sync_type sync_type){ + job_buffer buf = { + .worker_ptr = {.ptr = (uptr)ptr, .size = size}, + .orig_ptr = {.ptr = (uptr)ptr, .size = size}, + .sync = sync_type, + .arg_num = arg_num, + .explicit_size = explicit_size + }; + job_application_append_buffer(application, buf); +} + static inline void job_serialize_stat(job_application_t *application, int arg_num, fs_stat *stat){ job_buffer buf = { - .ptr = {.ptr = (uptr)stat, .size = sizeof(fs_stat)}, + .worker_ptr = {.ptr = (uptr)stat, .size = sizeof(fs_stat) }, + .orig_ptr = {.ptr = (uptr)stat, .size = sizeof(fs_stat) }, + .sync = copy_on_end, .arg_num = arg_num, - .explicit_size = false + .explicit_size = false, + }; + job_application_append_buffer(application, buf); +} + +static inline void job_serialize_off(job_application_t *application, int arg_num, file_offset *offset){ + job_buffer buf = { + .worker_ptr = {.ptr = (uptr)offset, .size = sizeof(file_offset *) }, + .orig_ptr = {.ptr = (uptr)offset, .size = sizeof(file_offset *) }, + .sync = copy_on_end, + .arg_num = arg_num, + .explicit_size = false, }; job_application_append_buffer(application, buf); } job_id_t create_new_job(job_application_t application); -void fulfill_job(job_id_t job_id, thread_t *thread); +void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread); diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 58b11a64..5f12a270 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -194,7 +194,7 @@ u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ kprintf("Thread has ended with code %i",current_thread->PROC_X0); syscall_depth--; if (current_thread->job_id){ - fulfill_job(current_thread->job_id, current_thread); + fulfill_job(current_thread->job_id, current_thread->PROC_X0, current_thread); } if (current_thread == &ctx->main_thread) stop_current_process(current_thread->PROC_X0); diff --git a/shared b/shared index 4cf55157..96ab6d8f 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 4cf5515704e3da9a30f7a381a791c58ce26c7a62 +Subproject commit 96ab6d8f8e07805320b9c69ceeb8bc3e1f8799fe diff --git a/user/terminal/main.c b/user/terminal/main.c index 3857767b..6b7a8a11 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -289,6 +289,13 @@ bool custom_stat(const char *path, fs_stat *out_stat){ return true; } +size_t custom_readdir(const char *path, void *buf, size_t size, file_offset *offset){ + print("READDIR %s info %x (%i) (%x)",path,buf,size,offset); + fs_dir_list_helper helper = create_dir_list_helper(buf, size); + dir_list_fill(&helper, "test"); + return dir_buf_size(&helper); +} + system_module termhistory_mod = { .name = "terminal history", .mount = "termhistory", @@ -297,7 +304,7 @@ system_module termhistory_mod = { .open = stackfs_open, .read = stackfs_read, .write = stackfs_write, - .readdir = stackfs_readdir, + .readdir = custom_readdir, .getstat = custom_stat }; From 1940b05fe0419dd50967a3b0d9170fc43bce813b Mon Sep 17 00:00:00 2001 From: di Date: Sat, 4 Jul 2026 00:00:00 +0000 Subject: [PATCH 20/65] [THREADING] stack cleanup --- kernel/process/scheduler.c | 1 + kernel/process/stack_manager.c | 16 +++++++++++++++- kernel/process/stack_manager.h | 3 ++- kernel/process/syscall.c | 2 ++ user/terminal/main.c | 1 - 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 98b290fe..7bebf1b5 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -297,6 +297,7 @@ void reset_process(process_t *proc){ proc->main_thread.sp = 0; proc->main_thread.pc = 0; proc->main_thread.spsr = 0; + unmap_stack(proc, proc->main_thread.stack_info); memset(proc->main_thread.regs, 0, 31 * sizeof(proc->main_thread.regs[0])); memset(&proc->input_buffer, 0, sizeof(proc->input_buffer)); memset(&proc->event_buffer, 0, sizeof(proc->event_buffer)); diff --git a/kernel/process/stack_manager.c b/kernel/process/stack_manager.c index 1d85f0a9..624a1cf0 100644 --- a/kernel/process/stack_manager.c +++ b/kernel/process/stack_manager.c @@ -1,9 +1,10 @@ #include "stack_manager.h" #include "exceptions/exception_handler.h" +#include "memory/mmu.h" uptr next_stack_addr(process_t *proc){ if (is_privileged(proc)) return 0; - for (uptr start = stack_max_addr; start > stack_min_addr; start -= 0x100000000000){ + for (uptr start = stack_max_addr; start > stack_min_addr; start -= stack_max + PAGE_SIZE){ vma *m = mm_find_vma(&proc->mm, start-stack_max); if (!m){ return start; @@ -13,6 +14,19 @@ uptr next_stack_addr(process_t *proc){ return 0; } +void unmap_stack(process_t *proc, stack_t stack){ + vma *m = mm_find_vma(&proc->mm, stack.top-stack_max); + if (m){ + for (uptr addr = stack.top-stack.size; addr < stack.top; addr += PAGE_SIZE){ + uptr pa = 0; + mmu_unmap_and_get_pa(proc->mm.ttbr0, addr, &pa); + if (pa) + pfree((void*)pa, PAGE_SIZE); + } + mm_remove_vma(&proc->mm, stack.top-stack.size, stack.top); + } +} + stack_t new_stack(process_t *proc){ uptr stack_top = 0; if (is_privileged(proc)) { diff --git a/kernel/process/stack_manager.h b/kernel/process/stack_manager.h index 0f7a780f..96e7883c 100644 --- a/kernel/process/stack_manager.h +++ b/kernel/process/stack_manager.h @@ -8,4 +8,5 @@ #define stack_distance (stack_max + PAGE_SIZE) #define stack_min_addr 0x100000000000ULL -stack_t new_stack(process_t *proc); \ No newline at end of file +stack_t new_stack(process_t *proc); +void unmap_stack(process_t *proc, stack_t stack); \ No newline at end of file diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 5f12a270..af7e00c5 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -35,6 +35,7 @@ #include "files/dir_list.h" #include "theme/theme.h" #include "jobs/job_manager.h" +#include "stack_manager.h" int syscall_depth = 0; uintptr_t cpec; @@ -201,6 +202,7 @@ u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ else { current_thread->thread_state = STOPPED; unschedule_thread(ctx, current_thread); + unmap_stack(ctx, current_thread->stack_info); switch_proc(YIELD);//TODO: proper cleanup } return 0; diff --git a/user/terminal/main.c b/user/terminal/main.c index 6b7a8a11..d6447122 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -300,7 +300,6 @@ system_module termhistory_mod = { .name = "terminal history", .mount = "termhistory", .version = VERSION_NUM(0, 1, 0, 0), - .init = 0, .open = stackfs_open, .read = stackfs_read, .write = stackfs_write, From cef074ea5896d717ce564531b2f8e99efdbc6cbf Mon Sep 17 00:00:00 2001 From: di Date: Mon, 6 Jul 2026 00:00:00 +0000 Subject: [PATCH 21/65] [JOB] open file job --- kernel/filesystem/filesystem.c | 40 +++++++++++++++---------- kernel/filesystem/filesystem.h | 1 + kernel/process/jobs/job_manager.c | 50 +++++++++++++++++++++++-------- kernel/process/jobs/job_manager.h | 12 ++++++++ shared | 2 +- user/filebrowser/main.c | 5 ++++ user/terminal/main.c | 10 ++++++- 7 files changed, 90 insertions(+), 30 deletions(-) diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index c907d8a1..ba4a38c4 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -47,31 +47,31 @@ bool init_filesystem(){ return true; } -FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor, system_module **mod){ +FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor, system_module **out_mod){ const char *search_path = path; if (*search_path == '/') search_path++; if (!*search_path) return FS_RESULT_NOTFOUND; - system_module *module = get_module_from(root, &search_path); - if (!module) return FS_RESULT_NOTFOUND; - if (!module->open) return FS_RESULT_NOTFOUND; + system_module *mod = get_module_from(root, &search_path); + if (!mod) return FS_RESULT_NOTFOUND; + if (!mod->open) return FS_RESULT_NOTFOUND; FS_RESULT result = FS_RESULT_DRIVER_ERROR; - if (module->owner != get_kernel_proc()->id){ - kprintf("cba rn"); - return result; + if (mod->owner != get_kernel_proc()->id){ + job_make(job_open, { + job_serialize_str(&app, 0, path); + job_serialize_fd(&app, 1, descriptor, copy_on_end); + }); + return 0; } else { - result = module->open(search_path, descriptor); + result = mod->open(search_path, descriptor); } if (result != FS_RESULT_SUCCESS) return result; if (!open_files) return FS_RESULT_DRIVER_ERROR; descriptor->cursor = 0; - *mod = module; + *out_mod = mod; return FS_RESULT_SUCCESS; } -FS_RESULT open_file(module_root *root, const char* path, file* descriptor){ - system_module *mod = 0; - FS_RESULT result = open_file_global(root, path, descriptor, &mod); - if (result != FS_RESULT_SUCCESS) return result; +FS_RESULT instance_local_fd(system_module *mod, file *descriptor){ open_file_descriptors *of = (open_file_descriptors*)open_files_alloc(sizeof(open_file_descriptors)); if (!of) { close_file_global(descriptor, mod); @@ -83,9 +83,7 @@ FS_RESULT open_file(module_root *root, const char* path, file* descriptor){ of->mod = mod; of->pid = get_current_proc_pid(); descriptor->id = of->file_id; - irq_flags_t irq = irq_save_disable(); int put = hash_map_put(open_files, &of->file_id, sizeof(uint64_t), of); - irq_restore(irq); if (put != 1) { file tmp = { @@ -97,9 +95,19 @@ FS_RESULT open_file(module_root *root, const char* path, file* descriptor){ release(of); return FS_RESULT_DRIVER_ERROR; } + return FS_RESULT_SUCCESS; } +FS_RESULT open_file(module_root *root, const char* path, file* descriptor){ + system_module *mod = 0; + FS_RESULT result = open_file_global(root, path, descriptor, &mod); + if (result != FS_RESULT_SUCCESS) return result; + result = instance_local_fd(mod, descriptor); + if (result != FS_RESULT_SUCCESS) return result; + return result; +} + size_t read_file(file *descriptor, char* buf, size_t size){ if (!open_files){ kprintf("[FS] No open files"); @@ -331,5 +339,5 @@ void close_files_for_process(uint16_t pid){ close_file(&fd); } } - close_pipes_for_process(pid); + close_pipes_for_process(pid);//TODO: pipes need to be cleaned. They're not being used } diff --git a/kernel/filesystem/filesystem.h b/kernel/filesystem/filesystem.h index 112c7844..54c2d786 100644 --- a/kernel/filesystem/filesystem.h +++ b/kernel/filesystem/filesystem.h @@ -11,6 +11,7 @@ extern "C" { FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor, system_module **mod); FS_RESULT open_file(module_root *root, const char* path, file* descriptor); +FS_RESULT instance_local_fd(system_module *mod, file *descriptor); size_t read_file(file *descriptor, char* buf, size_t size); size_t write_file(file *descriptor, const char* buf, size_t size); void close_file_global(file *descriptor, system_module *mod); diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 73ff52e7..42521c95 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -5,6 +5,7 @@ #include "memory/mmu.h" #include "memory/addr.h" #include "memory/memory.h" +#include "filesystem/filesystem.h" job_id_t job_id_counter = 1; @@ -14,6 +15,7 @@ typedef struct { job_id_t id; job_buffer buffers[8]; size_t buffer_count; + job_types type; } job_state_t; linked_list_t *job_list; @@ -38,6 +40,8 @@ bool prepare_thread(job_state_t *job, job_application_t application, process_t * switch (application.type){ case job_stat: entry = (uptr)proc->exposed_fs.getstat; break; case job_readdir: entry = (uptr)proc->exposed_fs.readdir; break; + case job_open: entry = (uptr)proc->exposed_fs.open; break; + case job_close: entry = (uptr)proc->exposed_fs.close; break; default: return false; } if (!entry) return false; @@ -59,7 +63,7 @@ bool prepare_thread(job_state_t *job, job_application_t application, process_t * for (size_t i = 0; i < application.buffer_count; i++){ job_buffer buf = application.buffers[i]; job->buffers[job->buffer_count++] = buf; - if (buf.sync == copy_on_start) + if (buf.sync & copy_on_start) memcpy((void*)next_addr_pa, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); t->regs[buf.arg_num] = next_addr_va; job->buffers[i].worker_ptr.ptr = next_addr_va; @@ -73,6 +77,7 @@ bool prepare_thread(job_state_t *job, job_application_t application, process_t * job_id_t create_new_job(job_application_t application){ job_state_t *job = job_alloc(); + job->type = application.type; process_t *requesting_proc = get_proc_by_pid(application.requesting_pid); if (!requesting_proc){ print("[JOB error] Unknown requesting proc %i",application.requesting_pid); @@ -99,6 +104,19 @@ job_state_t* get_job_state(job_id_t job_id){ return 0; } +void* quick_translate(thread_t *thread, process_t *proc, uptr ptr){ + int status = 0; + uptr addr = mmu_translate(proc->mm.ttbr0, ptr, &status); + if (status){ + uint64_t esr = (0x24ULL << 26) | 0x7ULL; + if (!mm_try_handle_page_fault(proc, thread, ptr, esr)) return 0; + + addr = mmu_translate((uint64_t*)proc->mm.ttbr0, ptr, &status); + if (status) return 0; + } + return (void*)PHYS_TO_VIRT(addr); +} + void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ job_state_t *st = get_job_state(job_id); if (!st) { @@ -109,25 +127,33 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ print("[JOB error] termination request by wrong thread %i",thread->tid); return; } - st->requester->thread_state = RUNNING;//TODO: schedule once the scheduler is fully thread-based process_t *proc = get_proc_by_pid(st->requester->pid); + process_t *fsproc = get_proc_by_pid(st->worker->pid); + // if (st->type == job_open){ + // process_t *fsproc = get_proc_by_pid(st->worker->pid); + // if (fsproc){ + // file* fd = quick_translate(st->requester, proc, (uptr)st->fd); + // instance_local_fd(&fsproc->exposed_fs, fd); + // } + // } + st->requester->thread_state = RUNNING;//TODO: schedule once the scheduler is fully thread-based proc->state = RUNNING;//TODO: this shouldn't be necessary ready_process(proc); st->requester->PROC_X0 = ret; for (size_t i = 0; i < st->buffer_count; i++){ job_buffer buf = st->buffers[i]; - if (buf.sync == copy_on_end){ + if (buf.sync & copy_on_end){ print("[JOB debug] Copy buffer %x into %x",buf.worker_ptr.ptr,buf.orig_ptr.ptr); - int status = 0; - uptr addr = mmu_translate(proc->mm.ttbr0, buf.orig_ptr.ptr, &status); - if (status){ - uint64_t esr = (0x24ULL << 26) | 0x7ULL; - if (!mm_try_handle_page_fault(proc, st->requester, buf.orig_ptr.ptr, esr)) return; - - addr = mmu_translate((uint64_t*)proc->mm.ttbr0, buf.orig_ptr.ptr, &status); - if (st) return; + void* addr = quick_translate(st->requester, proc, buf.orig_ptr.ptr); + if (!addr) return; + memcpy(addr, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); + file *fd = addr; + if (buf.fd){ + print("[JOB DEBUG] fd %i size %i signature %s",fd->id,fd->size,&fd->data_type); + if (st->type == job_open){ + instance_local_fd(&fsproc->exposed_fs, addr); + } } - memcpy((void*)PHYS_TO_VIRT(addr), (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); } } print("[JOB] %i fulfilled",job_id); diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index cc890636..68930271 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -50,6 +50,18 @@ static inline void job_serialize_buf(job_application_t *application, u8 arg_num, job_application_append_buffer(application, buf); } +static inline void job_serialize_fd(job_application_t *application, u8 arg_num, file *fd, job_sync_type sync_type){ + job_buffer buf = { + .worker_ptr = {.ptr = (uptr)fd, .size = sizeof(file)}, + .orig_ptr = {.ptr = (uptr)fd, .size = sizeof(file)}, + .sync = sync_type, + .arg_num = arg_num, + .explicit_size = false, + .fd = true + }; + job_application_append_buffer(application, buf); +} + static inline void job_serialize_stat(job_application_t *application, int arg_num, fs_stat *stat){ job_buffer buf = { .worker_ptr = {.ptr = (uptr)stat, .size = sizeof(fs_stat) }, diff --git a/shared b/shared index 96ab6d8f..f886c36e 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 96ab6d8f8e07805320b9c69ceeb8bc3e1f8799fe +Subproject commit f886c36ed605c9dc87170e1b094ede5304007d89 diff --git a/user/filebrowser/main.c b/user/filebrowser/main.c index 51bb16b5..2d57698a 100644 --- a/user/filebrowser/main.c +++ b/user/filebrowser/main.c @@ -6,6 +6,11 @@ int main(){ request_draw_ctx(&filebrowser_ctx); + + file descriptor = {}; + openf("/termhistory", &descriptor); + + print("Descriptor id %i of type %s and size %i",descriptor.id,&descriptor.data_type,descriptor.size); files = stack_create(sizeof(file_data),32); directories = stack_create(sizeof(string),16); diff --git a/user/terminal/main.c b/user/terminal/main.c index d6447122..47f36b57 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -296,11 +296,19 @@ size_t custom_readdir(const char *path, void *buf, size_t size, file_offset *off return dir_buf_size(&helper); } +FS_RESULT custom_open(const char *path, file *fd){ + fd->id = 1; + print("Sending id %i",fd->id); + fd->size = 100; + fd->data_type = DATA_SIGNATURE("ASYNC"); + return FS_RESULT_SUCCESS; +} + system_module termhistory_mod = { .name = "terminal history", .mount = "termhistory", .version = VERSION_NUM(0, 1, 0, 0), - .open = stackfs_open, + .open = custom_open, .read = stackfs_read, .write = stackfs_write, .readdir = custom_readdir, From 404c9fea1e42e3f18a71963af6c56549acd0635c Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 11 Jul 2026 00:00:00 +0000 Subject: [PATCH 22/65] [THREADING] enqueue threads instead of processes --- kernel/process/scheduler.c | 48 ++++++++++++++++++++++++-------------- kernel/process/scheduler.h | 1 + shared | 2 +- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 7bebf1b5..6a8c2211 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -47,7 +47,6 @@ process_t *process_list = 0; uint16_t proc_count = 0; uint16_t next_proc_index = 1; -//TODO maybe use a weighted ready queue based on process priority CQueue ready_queue = {}; linked_list_t sleeping_list = {}; @@ -87,11 +86,11 @@ bool process_can_reset(process_t *proc){ return proc && proc->state == STOPPED && proc->pending_reset && !proc->procfs_refs; } -void enqueue_ready_process(process_t *proc){ - if (!proc || proc == idle_proc || proc->state == READY) return; - if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); - if (!cqueue_enqueue(&ready_queue, &proc)) panic("ready enqueue failed", proc->id); - proc->state = READY; +void enqueue_ready_thread(thread_t *t){ + if (!t || t->pid == idle_proc->id || t->thread_state == READY) return; + if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(thread_t*),0,0); + t->thread_state = READY; + if (!cqueue_enqueue(&ready_queue, &t)) panic("ready enqueue failed", (t->pid << 16) | t->pid); } bool remove_sleeping_process(process_t *proc, uint16_t pid){ @@ -128,10 +127,11 @@ void update_sleep_timer() { void switch_proc(ProcSwitchReason reason) { if (proc_count == 0) panic("No processes active", 0); + thread_t *prev_t = (thread_t*)cpec; process_t *prev = current_proc, *next_proc = 0; - if (prev && prev->state == RUNNING) { + if (prev && prev->state == RUNNING && prev_t->thread_state == RUNNING) { if (prev == idle_proc) prev->state = BLOCKED; - else ready_process(prev); + else enqueue_ready_thread(prev_t); } if (prev->current_thread->next){ @@ -140,11 +140,12 @@ void switch_proc(ProcSwitchReason reason) { } while (prev->current_thread && prev->current_thread->thread_state != RUNNING && prev->current_thread->thread_state != READY); } else { while (!cqueue_is_empty(&ready_queue)) { - process_t *queued = 0; + thread_t *queued = 0; if (!cqueue_dequeue(&ready_queue, &queued)) break; if (!queued) continue; - if (queued->state != READY || !process_can_run(queued)) continue; - next_proc = queued; + if (queued->thread_state != READY) continue; + process_t *proc = get_proc_by_pid(queued->pid); + next_proc = (process_t*)proc; break; } } @@ -156,6 +157,7 @@ void switch_proc(ProcSwitchReason reason) { if (!next_proc->current_thread) next_proc->current_thread = &next_proc->main_thread; next_proc->state = RUNNING; + next_proc->current_thread->thread_state = RUNNING; current_proc = next_proc; cpec = (uptr)next_proc->current_thread; if (current_proc == idle_proc) timer_disable(); @@ -208,7 +210,6 @@ bool start_scheduler(){ } bool init_scheduler(){ - if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); load_module(&procfs_mod); return true; } @@ -247,7 +248,19 @@ void ready_process(process_t *proc){ proc->spsr = proc->main_thread.spsr;//TODO: remove - enqueue_ready_process(proc); + enqueue_ready_thread(&proc->main_thread); + proc->state = READY; + irq_restore(irq); +} + +void ready_thread(thread_t *t){ + irq_flags_t irq = irq_save_disable(); + if (!t || !t->pid || !t->tid || t->thread_state == STOPPED/* || thread->sleeping || proc->pending_reset*/) { + irq_restore(irq); + return; + } + + enqueue_ready_thread(t); irq_restore(irq); } @@ -471,7 +484,6 @@ void reset_process(process_t *proc){ } void init_main_process(){ - if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(process_t*),0,0); size_t kernel_proc_size = (sizeof(process_t) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); kernel_proc = (process_t*)palloc(kernel_proc_size, MEM_PRIV_KERNEL, MEM_RW, true); if (!kernel_proc) panic("kernel process alloc failed", 0); @@ -605,7 +617,7 @@ void block_process(process_t *proc){ void resume_blocked_process(process_t *proc){ proc->suspended = false; - enqueue_ready_process(proc); + enqueue_ready_thread(&proc->main_thread); } uint16_t process_count(){ @@ -660,7 +672,7 @@ void wake_process(process_t *proc){ proc->sleeping = false; proc->wake_at_msec = 0; - if (proc->state == BLOCKED) enqueue_ready_process(proc); + if (proc->state == BLOCKED) enqueue_ready_thread(&proc->main_thread); } update_sleep_timer(); @@ -685,7 +697,7 @@ void wake_processes(){ proc->sleeping = false; proc->wake_at_msec = 0; - if (proc->state != STOPPED) enqueue_ready_process(proc); + if (proc->state != STOPPED) enqueue_ready_thread(&proc->main_thread); } } @@ -720,7 +732,7 @@ void schedule_thread(process_t *proc, thread_t *t){ current->next = t; proc->thread_count++; kprintf("[SCHEDULER] scheduled thread %i for %i. pc %llx",t->tid,t->pid,t->pc); - t->thread_state = RUNNING; + t->thread_state = READY; return; } current = current->next; diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 067166a0..12f34fe0 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -28,6 +28,7 @@ void save_return_address_interrupt(); void init_main_process(); process_t* init_process(); void ready_process(process_t *proc); +void ready_thread(thread_t *t); void save_syscall_return(uint64_t value); void process_restore(); diff --git a/shared b/shared index f886c36e..75738bf8 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit f886c36ed605c9dc87170e1b094ede5304007d89 +Subproject commit 75738bf8b7abe967798f6950c262f8423e718ec5 From e6d65db03aff7bf62e7f08ae5f541ec23b5ded71 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 11 Jul 2026 00:00:00 +0000 Subject: [PATCH 23/65] [PROC] cleaner process/thread definition --- kernel/memory/mm_process.h | 4 ++-- kernel/process/process.h | 12 ++++++------ kernel/process/signals/signals.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/memory/mm_process.h b/kernel/memory/mm_process.h index 6454abaa..19ba941c 100644 --- a/kernel/memory/mm_process.h +++ b/kernel/memory/mm_process.h @@ -3,8 +3,8 @@ #include "types.h" #include "memory/page_allocator.h" -typedef struct process process_t; -typedef struct thread thread_t; +typedef struct process_t process_t; +typedef struct thread_t thread_t; #define VMA_FLAG_DEMAND 1 #define VMA_FLAG_USERALLOC 2 diff --git a/kernel/process/process.h b/kernel/process/process.h index 1799349c..d89f7126 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -64,7 +64,7 @@ typedef struct { size_t size; } stack_t; -typedef struct thread { +struct thread_t { uint64_t regs[31]; // x0–x30 uintptr_t sp; uintptr_t pc; @@ -74,11 +74,11 @@ typedef struct thread { u16 pid; u16 tid; process_state thread_state; - struct thread *next; + thread_t *next; job_id_t job_id; -} thread_t; +}; -typedef struct process { +struct process_t { thread_t main_thread; uint16_t id; bool sleeping; @@ -124,8 +124,8 @@ typedef struct process { int thread_ids; environment_data environment; uptr shared_page; - struct process *process_next; -} process_t; + process_t *process_next; +}; static inline bool is_privileged(process_t *proc){ return proc->spsr & 0xf; diff --git a/kernel/process/signals/signals.h b/kernel/process/signals/signals.h index 6e965554..aad0d3e8 100644 --- a/kernel/process/signals/signals.h +++ b/kernel/process/signals/signals.h @@ -2,7 +2,7 @@ #include "signals/signal_types.h" -typedef struct process process_t; +typedef struct process_t process_t; extern process_t* get_proc_by_pid(uint16_t pid); bool register_signal_handler(process_t* proc, signal_types type, signal_handler handler); From af944a6e886064ead28bb7cc1da7c53fdf76be0e Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sat, 11 Jul 2026 00:00:00 +0000 Subject: [PATCH 24/65] [THREADING] thread-based sleep --- kernel/process/process.h | 9 +++--- kernel/process/scheduler.c | 57 ++++++++++++-------------------------- kernel/process/scheduler.h | 1 - shared | 2 +- 4 files changed, 24 insertions(+), 45 deletions(-) diff --git a/kernel/process/process.h b/kernel/process/process.h index d89f7126..6916d1cb 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -73,7 +73,8 @@ struct thread_t { stack_t stack_info; u16 pid; u16 tid; - process_state thread_state; + process_state thread_state;//NOTE: name will change to just state + u64 wake_at_msec; thread_t *next; job_id_t job_id; }; @@ -81,10 +82,10 @@ struct thread_t { struct process_t { thread_t main_thread; uint16_t id; - bool sleeping; - thread_t *current_thread;//NOTE: temporary + bool sleeping;//NOTE: deprecated + thread_t *current_thread;//NOTE: deprecated bool suspended; - uint64_t wake_at_msec; + uint64_t wake_at_msec;//NOTE: deprecated paddr_t heap_phys; kaddr_t output; size_t output_size; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 6a8c2211..b52bff84 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -98,8 +98,8 @@ bool remove_sleeping_process(process_t *proc, uint16_t pid){ linked_list_node_t *sleep = sleeping_list.head; while (sleep) { linked_list_node_t *next = sleep->next; - process_t *sleep_proc = (process_t*)sleep->data; - if (sleep_proc == proc || (sleep_proc && sleep_proc->id == pid)) { + thread_t *thread = (thread_t*)sleep->data; + if (thread && thread->pid == pid) { linked_list_remove(&sleeping_list, sleep); removed = true; } @@ -114,10 +114,10 @@ void save_return_address_interrupt(){ void update_sleep_timer() { if (sleeping_list.head) { - process_t *head_proc = (process_t*)sleeping_list.head->data; - if (head_proc) { + thread_t *head_thread = (thread_t*)sleeping_list.head->data; + if (head_thread) { uint64_t now = timer_now_msec(); - uint64_t wait = head_proc->wake_at_msec > now ? head_proc->wake_at_msec - now : 1; + uint64_t wait = head_thread->wake_at_msec > now ? head_thread->wake_at_msec - now : 1; virtual_timer_reset(wait); virtual_timer_enable(); } else virtual_timer_disable(); @@ -638,20 +638,20 @@ void sleep_process(uint64_t msec){ } uint64_t wake_at = timer_now_msec() + msec; - current_proc->state = BLOCKED; - current_proc->sleeping = true; - current_proc->wake_at_msec = wake_at; + thread_t *current_thread = (thread_t*)cpec; + current_thread->thread_state = BLOCKED; + current_thread->wake_at_msec = wake_at; linked_list_node_t *it = sleeping_list.head, *prev = 0; while (it) { - process_t *cur = (process_t*)it->data; + thread_t *cur = (thread_t*)it->data; if (!cur || cur->wake_at_msec > wake_at) break; prev = it; it = it->next; } - linked_list_insert_after(&sleeping_list, prev, current_proc); - if (sleeping_list.head && sleeping_list.head->data == current_proc){ + linked_list_insert_after(&sleeping_list, prev, current_thread); + if (sleeping_list.head && sleeping_list.head->data == current_thread){ virtual_timer_reset(msec); virtual_timer_enable(); } @@ -659,45 +659,24 @@ void sleep_process(uint64_t msec){ irq_restore(irq); } -void wake_process(process_t *proc){ - if (!proc) return; - irq_flags_t irq = irq_save_disable(); - - if (proc->state == STOPPED) { - irq_restore(irq); - return; - } - - if (remove_sleeping_process(proc, proc->id)) { - proc->sleeping = false; - proc->wake_at_msec = 0; - - if (proc->state == BLOCKED) enqueue_ready_thread(&proc->main_thread); - } - - update_sleep_timer(); - irq_restore(irq); -} - void wake_processes(){ irq_flags_t irq = irq_save_disable(); uint64_t now = timer_now_msec(); while (sleeping_list.head) { - process_t *proc = (process_t*)sleeping_list.head->data; + thread_t *t = (thread_t*)sleeping_list.head->data; - if (!proc) { + if (!t) { linked_list_pop_front(&sleeping_list); continue; } - if (proc->wake_at_msec > now) break; - proc = (process_t*)linked_list_pop_front(&sleeping_list); + if (t->wake_at_msec > now) break; + t = (thread_t*)linked_list_pop_front(&sleeping_list); - if (proc) { - proc->sleeping = false; - proc->wake_at_msec = 0; + if (t) { + t->wake_at_msec = 0; - if (proc->state != STOPPED) enqueue_ready_thread(&proc->main_thread); + if (t->thread_state != STOPPED) enqueue_ready_thread(t); } } diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 12f34fe0..f85fbf1b 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -43,7 +43,6 @@ void name_process(process_t *proc, const char *name); void sleep_process(uint64_t msec); void wake_processes(); -void wake_process(process_t *proc); bool load_process_module(process_t *p, system_module *m); diff --git a/shared b/shared index 75738bf8..49101489 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 75738bf8b7abe967798f6950c262f8423e718ec5 +Subproject commit 49101489e7f616b925ee7f0439634cc5fb686df6 From bf6c7511e452bed08448c73339ff8335c219810c Mon Sep 17 00:00:00 2001 From: di Date: Wed, 15 Jul 2026 00:00:00 +0000 Subject: [PATCH 25/65] [BUILD] makefile error cleanup --- Makefile | 1 - modules/MakefileModule | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index e47e9942..993aa303 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,6 @@ dump: $(ARCH)objdump -S -D kernel.elf > dump $(MAKE) -C user $@ $(MAKE) -C tools $@ - $(MAKE) -C modules $@ install: $(MAKE) clean diff --git a/modules/MakefileModule b/modules/MakefileModule index 97e8ef2a..434ec1fd 100644 --- a/modules/MakefileModule +++ b/modules/MakefileModule @@ -13,11 +13,11 @@ endif CFLAGS := $(CFLAGS_BASE) $(BASE_FLAGS) CXXFLAGS := $(CXXFLAGS_BASE) $(BASE_FLAGS) -CLEAN_OBJS := $(shell find $(DRIVER_TARGET) -name "*.o") $(shell find ./common -name "*.o") -CLEAN_DEPS := $(shell find $(DRIVER_TARGET) -name "*.d") $(shell find ./common -name "*.d") -C_SRC := $(shell find $(DRIVER_TARGET) -name "*.c") $(shell find ./common -name "*.c") -CPP_SRC := $(shell find $(DRIVER_TARGET) -name "*.cpp") $(shell find ./common -name "*.cpp") -ASM_SRC := $(shell find $(DRIVER_TARGET) -name "*.S") $(shell find ./common -name "*.S") +CLEAN_OBJS := $(shell find $(DRIVER_TARGET) -name "*.o") $(shell find ./common -name "*.o" 2>/dev/null) +CLEAN_DEPS := $(shell find $(DRIVER_TARGET) -name "*.d") $(shell find ./common -name "*.d" 2>/dev/null) +C_SRC := $(shell find $(DRIVER_TARGET) -name "*.c") $(shell find ./common -name "*.c" 2>/dev/null) +CPP_SRC := $(shell find $(DRIVER_TARGET) -name "*.cpp") $(shell find ./common -name "*.cpp" 2>/dev/null) +ASM_SRC := $(shell find $(DRIVER_TARGET) -name "*.S") $(shell find ./common -name "*.S" 2>/dev/null) OBJ := $(C_SRC:%.c=$(BUILD_DIR)/%.o) $(ASM_SRC:%.S=$(BUILD_DIR)/%.o) $(CPP_SRC:%.cpp=$(BUILD_DIR)/%.o) DEP := $(C_SRC:%.c=$(BUILD_DIR)/%.d) $(ASM_SRC:%.S=$(BUILD_DIR)/%.d) $(CPP_SRC:%.cpp=$(BUILD_DIR)/%.d) From 833abffd7710326fee4311ae0ef185c902cb8db6 Mon Sep 17 00:00:00 2001 From: di Date: Wed, 15 Jul 2026 00:00:00 +0000 Subject: [PATCH 26/65] [FAT32] correct mem alloc for writing --- kernel/filesystem/fat32.cpp | 2 +- shared | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 34fd96ec..ea78b578 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -114,7 +114,7 @@ bool FAT32FS::write_section_to_cluster(u32 cluster, u32 offset, void *buf, size_ u32 sector_count = ceil(((float)offset + size)/512); - void *initial = zalloc(512 * sector_count); + void *initial = kalloc(fs_page, 512 * sector_count, ALIGN_64B, MEM_PRIV_KERNEL); disk_read(initial, sector, sector_count); diff --git a/shared b/shared index f886c36e..49101489 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit f886c36ed605c9dc87170e1b094ede5304007d89 +Subproject commit 49101489e7f616b925ee7f0439634cc5fb686df6 From 1187c87cfd48f8a001eecc6ffd766767f3f7116c Mon Sep 17 00:00:00 2001 From: di Date: Wed, 15 Jul 2026 00:00:00 +0000 Subject: [PATCH 27/65] [TRES] window fallback fix --- kernel/graph/tres.c | 6 +++++- kernel/process/scheduler.c | 2 ++ libs/LibMakefile | 5 ----- shared | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/kernel/graph/tres.c b/kernel/graph/tres.c index 039af3f4..7d8094b6 100644 --- a/kernel/graph/tres.c +++ b/kernel/graph/tres.c @@ -287,8 +287,11 @@ u16 window_fallback_focus(u16 win_id, u16 skip_id){ if (!node || !node->data) return 0; window_frame *frame = node->data; - if (frame->pid != skip_id) + if (frame->pid != skip_id){ + process_t *proc = get_proc_by_pid(frame->pid); + proc->focused = true; return frame->pid; + } process_t *proc = get_all_processes(); while (proc) { @@ -296,6 +299,7 @@ u16 window_fallback_focus(u16 win_id, u16 skip_id){ frame->pid = proc->id; if (proc->graphics_ctx.fb){ frame->win_ctx.fb = proc->graphics_ctx.fb; + proc->focused = true; if (proc->graphics_ctx.width != frame->width || proc->graphics_ctx.height != frame->height){ frame->width = proc->graphics_ctx.width; frame->height = proc->graphics_ctx.height; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index b52bff84..87a8501a 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -602,6 +602,8 @@ void stop_process(uint16_t pid, int32_t exit_code){ return; } + //TODO: any threads for this process with a job id need to be reported back as failed + if (proc->mm.ttbr0) mmu_swap_ttbr(0); switch_proc(HALT); panic("stop_process returned", pid); diff --git a/libs/LibMakefile b/libs/LibMakefile index ca515c3d..938b0ad5 100644 --- a/libs/LibMakefile +++ b/libs/LibMakefile @@ -1,8 +1,3 @@ -#Find the simplemake - #Iterate through each line - #gcc -I../../shared -c file.c -o file.o ../../shared/libshared.a - #Iterate through each line with .o and run - #ar rcs (folder).a *.o BASE_FLAGS := -I. -I../../shared diff --git a/shared b/shared index 49101489..326c0cb9 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 49101489e7f616b925ee7f0439634cc5fb686df6 +Subproject commit 326c0cb99ca5423ec1fdea98dbc5449846610822 From 2bbe49d0f90fb24c733a243f9fedbad54b4a79c5 Mon Sep 17 00:00:00 2001 From: di Date: Wed, 15 Jul 2026 00:00:00 +0000 Subject: [PATCH 28/65] [PROC] manual assign shared page return to main thread --- kernel/process/loading/process_loader.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index 8b69e7ed..9b1b74f5 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -407,6 +407,7 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->shared_page = shared_base; + proc->main_thread.regs[30] = proc->shared_page; kprintf("[NEW PROC:U]: %s (pid: %i, main tid: %i) allocated at %llx entry=%llx stack=%llx-%llx anon=%llx (phys=%llx)", name, proc->id, proc->main_thread.tid, proc, (uint64_t)proc->main_thread.pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); proc->state = BLOCKED; From 01cbdfdfabdcd8c33212965c328e29e169c996ea Mon Sep 17 00:00:00 2001 From: di Date: Wed, 15 Jul 2026 00:00:00 +0000 Subject: [PATCH 29/65] [PROC] sleep state --- kernel/process/process.h | 6 ++---- kernel/process/scheduler.c | 17 +++++------------ shared | 2 +- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/kernel/process/process.h b/kernel/process/process.h index 6916d1cb..16afabdc 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -56,7 +56,7 @@ typedef struct { u64 fs_id; } system_permissions; -typedef enum { STOPPED, READY, RUNNING, BLOCKED } process_state; +typedef enum { STOPPED, READY, RUNNING, BLOCKED, SLEEPING } process_state; typedef struct { uptr top; @@ -82,10 +82,8 @@ struct thread_t { struct process_t { thread_t main_thread; uint16_t id; - bool sleeping;//NOTE: deprecated - thread_t *current_thread;//NOTE: deprecated + thread_t *current_thread; bool suspended; - uint64_t wake_at_msec;//NOTE: deprecated paddr_t heap_phys; kaddr_t output; size_t output_size; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 87a8501a..98c4a367 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -74,10 +74,10 @@ bool process_has_runtime_state(process_t *proc){ return proc && (proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack_info.size || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); } -bool process_can_run(process_t *proc){ +bool process_can_run(process_t *proc){//TODO: thread, not proc based if (!proc) return false; if (!process_is_known(proc) || proc->pending_reset) return false; - if (proc->state == STOPPED || proc->sleeping || proc->suspended || !proc->main_thread.pc || !proc->main_thread.sp) return false; + if (proc->state == STOPPED || proc->suspended || !proc->main_thread.pc || !proc->main_thread.sp) return false; if (!is_privileged(proc)) return !!proc->mm.ttbr0; return !proc->mm.ttbr0; } @@ -185,7 +185,6 @@ void process_restore(){ if (current_proc->mm.ttbr0) { current_proc->pending_reset = true; current_proc->state = STOPPED; - current_proc->sleeping = false; switch_proc(HALT); panic("process_restore recovery returned", cpec); } @@ -241,7 +240,7 @@ bool scheduler_in_idle(){ void ready_process(process_t *proc){ irq_flags_t irq = irq_save_disable(); - if (!proc || !proc->id || proc->state == STOPPED || proc->sleeping || proc->pending_reset) { + if (!proc || !proc->id || proc->state == STOPPED || proc->pending_reset) { irq_restore(irq); return; } @@ -255,7 +254,7 @@ void ready_process(process_t *proc){ void ready_thread(thread_t *t){ irq_flags_t irq = irq_save_disable(); - if (!t || !t->pid || !t->tid || t->thread_state == STOPPED/* || thread->sleeping || proc->pending_reset*/) { + if (!t || !t->pid || !t->tid || t->thread_state == STOPPED || t->thread_state == SLEEPING/* || proc->pending_reset*/) { irq_restore(irq); return; } @@ -298,8 +297,6 @@ void reset_process(process_t *proc){ irq_flags_t irq = irq_save_disable(); proc->pending_reset = false; - proc->sleeping = false; - proc->wake_at_msec = 0; proc->thread_count = 0;//TODO: clean up all threads proc->thread_ids = 0; @@ -530,8 +527,6 @@ process_t* init_process(){ proc->exit_code = 0; proc->state = BLOCKED; proc->priority = PROC_PRIORITY_LOW; - proc->sleeping = false; - proc->wake_at_msec = 0; proc->pending_reset = false; proc_count++; irq_restore(irq); @@ -590,8 +585,6 @@ void stop_process(uint16_t pid, int32_t exit_code){ kprintf("[SCHEDULER] Stop process %i with code %i",proc->id,proc->exit_code); - proc->sleeping = false; - proc->wake_at_msec = 0; if (proc->focused) sys_unset_focus(false); @@ -641,7 +634,7 @@ void sleep_process(uint64_t msec){ uint64_t wake_at = timer_now_msec() + msec; thread_t *current_thread = (thread_t*)cpec; - current_thread->thread_state = BLOCKED; + current_thread->thread_state = SLEEPING; current_thread->wake_at_msec = wake_at; linked_list_node_t *it = sleeping_list.head, *prev = 0; diff --git a/shared b/shared index 326c0cb9..fab45a86 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 326c0cb99ca5423ec1fdea98dbc5449846610822 +Subproject commit fab45a86058e1a97165ef342a32967205d11a985 From eca5d638ba565992c9b5667d133315edbccc5577 Mon Sep 17 00:00:00 2001 From: di Date: Wed, 15 Jul 2026 00:00:00 +0000 Subject: [PATCH 30/65] [PROC] proc full memset 0 on reset --- kernel/process/scheduler.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 98c4a367..3c4d7bce 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -478,6 +478,8 @@ void reset_process(process_t *proc){ proc->id = pid; proc->exit_code = exit_code; proc->state = STOPPED; + + memset(proc, 0, sizeof(process_t)); } void init_main_process(){ From 8c2f6e897c9439470b8fcbeebd2edb8c97c37e5d Mon Sep 17 00:00:00 2001 From: di Date: Wed, 15 Jul 2026 00:00:00 +0000 Subject: [PATCH 31/65] [PROC] privileged process stack fix (wow) --- kernel/memory/page_allocator.c | 2 +- kernel/process/stack_manager.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/memory/page_allocator.c b/kernel/memory/page_allocator.c index 8a8930a5..78919279 100644 --- a/kernel/memory/page_allocator.c +++ b/kernel/memory/page_allocator.c @@ -240,7 +240,7 @@ paddr_t palloc_inner(uint64_t size, uint8_t level, uint8_t attributes, bool full if (prev_page) prev_page->next = curr; prev_page = curr; - memset((void*)PHYS_TO_VIRT(address +sizeof(mem_page)), 0, PAGE_SIZE - sizeof(mem_page)); + memset((void*)PHYS_TO_VIRT(address + sizeof(mem_page)), 0, PAGE_SIZE - sizeof(mem_page)); } else { memset((void*)PHYS_TO_VIRT(address), 0, PAGE_SIZE); } diff --git a/kernel/process/stack_manager.c b/kernel/process/stack_manager.c index 624a1cf0..aed049a5 100644 --- a/kernel/process/stack_manager.c +++ b/kernel/process/stack_manager.c @@ -31,13 +31,13 @@ stack_t new_stack(process_t *proc){ uptr stack_top = 0; if (is_privileged(proc)) { void *st = palloc(stack_max, MEM_PRIV_KERNEL, MEM_RW, true); - stack_top = (uptr)st; + stack_top = (uptr)st + stack_max; register_allocation(proc->alloc_map, st, stack_max); } else stack_top = next_stack_addr(proc); if (!stack_top) return (stack_t){}; uptr stack_limit = stack_top - stack_max; print("New stack at %llx-%llx",stack_limit,stack_top); - if (!mm_add_vma(&proc->mm, stack_limit, stack_top, MEM_RW, VMA_KIND_STACK, VMA_FLAG_DEMAND)) + if (!is_privileged(proc) && !mm_add_vma(&proc->mm, stack_limit, stack_top, MEM_RW, VMA_KIND_STACK, VMA_FLAG_DEMAND)) return (stack_t){}; return (stack_t){.top = stack_top, .size = stack_max, .max = stack_max}; } \ No newline at end of file From 132e5e81b6bc6e5d923df4be177699e248bbee32 Mon Sep 17 00:00:00 2001 From: di Date: Wed, 15 Jul 2026 00:00:00 +0000 Subject: [PATCH 32/65] [PROC] undo full wipe, linked list needs to be kept --- kernel/process/scheduler.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 3c4d7bce..98c4a367 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -478,8 +478,6 @@ void reset_process(process_t *proc){ proc->id = pid; proc->exit_code = exit_code; proc->state = STOPPED; - - memset(proc, 0, sizeof(process_t)); } void init_main_process(){ From 1908444948e0a4478e40fdea8197118e2a170a4c Mon Sep 17 00:00:00 2001 From: di Date: Wed, 15 Jul 2026 00:00:00 +0000 Subject: [PATCH 33/65] [PROC] thread_state to state --- kernel/process/jobs/job_manager.c | 4 ++-- kernel/process/process.h | 2 +- kernel/process/scheduler.c | 20 ++++++++++---------- kernel/process/syscall.c | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 42521c95..e93d7dda 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -90,7 +90,7 @@ job_id_t create_new_job(job_application_t application){ if (!prepare_thread(job, application, fs_owner, new_t)) return false; new_t->job_id = job->id; job->worker = new_t; - requester->thread_state = BLOCKED; + requester->state = BLOCKED; requesting_proc->state = BLOCKED; schedule_thread(fs_owner, new_t); return job->id; @@ -136,7 +136,7 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ // instance_local_fd(&fsproc->exposed_fs, fd); // } // } - st->requester->thread_state = RUNNING;//TODO: schedule once the scheduler is fully thread-based + st->requester->state = RUNNING;//TODO: schedule once the scheduler is fully thread-based proc->state = RUNNING;//TODO: this shouldn't be necessary ready_process(proc); st->requester->PROC_X0 = ret; diff --git a/kernel/process/process.h b/kernel/process/process.h index 16afabdc..9c10534d 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -73,7 +73,7 @@ struct thread_t { stack_t stack_info; u16 pid; u16 tid; - process_state thread_state;//NOTE: name will change to just state + process_state state; u64 wake_at_msec; thread_t *next; job_id_t job_id; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 98c4a367..15e2fe51 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -87,9 +87,9 @@ bool process_can_reset(process_t *proc){ } void enqueue_ready_thread(thread_t *t){ - if (!t || t->pid == idle_proc->id || t->thread_state == READY) return; + if (!t || t->pid == idle_proc->id || t->state == READY) return; if (!ready_queue.elem_size) cqueue_init(&ready_queue, 0, sizeof(thread_t*),0,0); - t->thread_state = READY; + t->state = READY; if (!cqueue_enqueue(&ready_queue, &t)) panic("ready enqueue failed", (t->pid << 16) | t->pid); } @@ -129,7 +129,7 @@ void switch_proc(ProcSwitchReason reason) { panic("No processes active", 0); thread_t *prev_t = (thread_t*)cpec; process_t *prev = current_proc, *next_proc = 0; - if (prev && prev->state == RUNNING && prev_t->thread_state == RUNNING) { + if (prev && prev->state == RUNNING && prev_t->state == RUNNING) { if (prev == idle_proc) prev->state = BLOCKED; else enqueue_ready_thread(prev_t); } @@ -137,13 +137,13 @@ void switch_proc(ProcSwitchReason reason) { if (prev->current_thread->next){ do { prev->current_thread = prev->current_thread->next; - } while (prev->current_thread && prev->current_thread->thread_state != RUNNING && prev->current_thread->thread_state != READY); + } while (prev->current_thread && prev->current_thread->state != RUNNING && prev->current_thread->state != READY); } else { while (!cqueue_is_empty(&ready_queue)) { thread_t *queued = 0; if (!cqueue_dequeue(&ready_queue, &queued)) break; if (!queued) continue; - if (queued->thread_state != READY) continue; + if (queued->state != READY) continue; process_t *proc = get_proc_by_pid(queued->pid); next_proc = (process_t*)proc; break; @@ -157,7 +157,7 @@ void switch_proc(ProcSwitchReason reason) { if (!next_proc->current_thread) next_proc->current_thread = &next_proc->main_thread; next_proc->state = RUNNING; - next_proc->current_thread->thread_state = RUNNING; + next_proc->current_thread->state = RUNNING; current_proc = next_proc; cpec = (uptr)next_proc->current_thread; if (current_proc == idle_proc) timer_disable(); @@ -254,7 +254,7 @@ void ready_process(process_t *proc){ void ready_thread(thread_t *t){ irq_flags_t irq = irq_save_disable(); - if (!t || !t->pid || !t->tid || t->thread_state == STOPPED || t->thread_state == SLEEPING/* || proc->pending_reset*/) { + if (!t || !t->pid || !t->tid || t->state == STOPPED || t->state == SLEEPING/* || proc->pending_reset*/) { irq_restore(irq); return; } @@ -634,7 +634,7 @@ void sleep_process(uint64_t msec){ uint64_t wake_at = timer_now_msec() + msec; thread_t *current_thread = (thread_t*)cpec; - current_thread->thread_state = SLEEPING; + current_thread->state = SLEEPING; current_thread->wake_at_msec = wake_at; linked_list_node_t *it = sleeping_list.head, *prev = 0; @@ -671,7 +671,7 @@ void wake_processes(){ if (t) { t->wake_at_msec = 0; - if (t->thread_state != STOPPED) enqueue_ready_thread(t); + if (t->state != STOPPED) enqueue_ready_thread(t); } } @@ -706,7 +706,7 @@ void schedule_thread(process_t *proc, thread_t *t){ current->next = t; proc->thread_count++; kprintf("[SCHEDULER] scheduled thread %i for %i. pc %llx",t->tid,t->pid,t->pc); - t->thread_state = READY; + t->state = READY; return; } current = current->next; diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index af7e00c5..8cbaed62 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -200,7 +200,7 @@ u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ if (current_thread == &ctx->main_thread) stop_current_process(current_thread->PROC_X0); else { - current_thread->thread_state = STOPPED; + current_thread->state = STOPPED; unschedule_thread(ctx, current_thread); unmap_stack(ctx, current_thread->stack_info); switch_proc(YIELD);//TODO: proper cleanup From 937338b0518af5a439b4db719a3dc9969d88f38d Mon Sep 17 00:00:00 2001 From: di Date: Sat, 18 Jul 2026 00:00:00 +0000 Subject: [PATCH 34/65] [LAUNCHER] fail to load keeps launcher open --- user/launcher/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/user/launcher/main.c b/user/launcher/main.c index 6560aeca..5ae2c64b 100644 --- a/user/launcher/main.c +++ b/user/launcher/main.c @@ -181,6 +181,7 @@ void activate_current(){ u16 pid = exec(entry->path.data, 0, 0, EXEC_MODE_DEFAULT); if (!pid) { print("[LAUNCHER error] failed to launch process"); + rendered_full = false; return; } halt(0);//TODO: remove any references to resuming after the process is closed From 56a1875ca69c5aebc81bcb1700426233e62d5fa7 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 24 Jul 2026 00:00:00 +0000 Subject: [PATCH 35/65] [DESKTOP] (empty) menu bar [WINDOWS] (empty) tool/tabbar --- kernel/graph/tres.c | 7 +++-- kernel/graph/tres.h | 3 ++ kernel/kernel_processes/windows/dos.c | 34 +++++++++++++++++------ kernel/kernel_processes/windows/wincomp.c | 2 +- kernel/theme/theme.c | 2 +- shared | 2 +- user/terminal/main.c | 2 +- 7 files changed, 37 insertions(+), 15 deletions(-) diff --git a/kernel/graph/tres.c b/kernel/graph/tres.c index 7d8094b6..df62f337 100644 --- a/kernel/graph/tres.c +++ b/kernel/graph/tres.c @@ -24,7 +24,7 @@ i32 zoom_scale = 1; uint16_t win_ids = 1; bool dirty_windows = false; -int_point global_win_offset; +int_point global_win_offset = {}; draw_ctx non_win_ctx; @@ -111,6 +111,7 @@ void check_collisions(window_frame *frame){ } bool create_window(i32 x, i32 y, u32 width, u32 height){ + height -= TOOLBAR_HEIGHT; irq_flags_t irq = irq_save_disable(); if (win_ids == UINT16_MAX){ irq_restore(irq); @@ -260,7 +261,7 @@ void commit_frame(draw_ctx* frame_ctx, window_frame* frame, bool overwrite_focus memcpy(&non_win_ctx.dirty_rects, frame_ctx->dirty_rects, sizeof(non_win_ctx.dirty_rects)); non_win_ctx.dirty_count = frame_ctx->dirty_count; non_win_ctx.full_redraw = frame_ctx->full_redraw; - composite(&non_win_ctx, (int_point){}, 1, screen_ctx); + composite(&non_win_ctx, (int_point){}, 1, screen_ctx, (gpu_rect){ {0, MENU_HEIGHT}, {screen_ctx->width, screen_ctx->height-MENU_HEIGHT} }); } if (!frame){ linked_list_node_t *node = linked_list_find(window_list, PHYS_TO_VIRT_P(&p->win_id), PHYS_TO_VIRT_P(find_window)); @@ -275,7 +276,7 @@ void commit_frame(draw_ctx* frame_ctx, window_frame* frame, bool overwrite_focus win_ctx.dirty_count = frame_ctx->dirty_count; win_ctx.full_redraw = frame_ctx->full_redraw; - composite(&win_ctx, (int_point){global_win_offset.x + frame->x,global_win_offset.y + frame->y}, zoom_scale, screen_ctx); + composite(&win_ctx, (int_point){ global_win_offset.x + frame->x, global_win_offset.y + frame->y + TOOLBAR_HEIGHT }, zoom_scale, screen_ctx, (gpu_rect){ {0, MENU_HEIGHT}, {screen_ctx->width, screen_ctx->height-MENU_HEIGHT} }); frame_ctx->dirty_count = 0; frame_ctx->full_redraw = false; diff --git a/kernel/graph/tres.h b/kernel/graph/tres.h index b78cbe6e..16ba8795 100644 --- a/kernel/graph/tres.h +++ b/kernel/graph/tres.h @@ -16,6 +16,9 @@ typedef struct { uint16_t pid; } window_frame; +#define MENU_HEIGHT 50 +#define TOOLBAR_HEIGHT 50 + void init_window_manager(); bool create_window(int32_t x, int32_t y, uint32_t width, uint32_t height); diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 6df6f1fd..04c9dff1 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -35,22 +35,29 @@ static draw_ctx *dos_ctx; extern i32 zoom_scale; static void draw_solid_window(draw_ctx *ctx, int_point fixed_point, gpu_size fixed_size, bool fill){ + int_point win_point = {fixed_point.x + BORDER_SIZE, fixed_point.y + BORDER_SIZE + TOOLBAR_HEIGHT}; + gpu_size win_size = {fixed_size.width - (BORDER_SIZE*2), fixed_size.height - TOOLBAR_HEIGHT - (BORDER_SIZE*2)}; DRAW(rectangle(ctx, (rect_ui_config){ .border_size = BORDER_SIZE, .border_color = system_theme.bg_color + 0x222222 }, (common_ui_config){ .point = fixed_point, .size = fixed_size, - .background_color = system_theme.bg_color, + .background_color = system_theme.bg_color + 0x111111, .foreground_color = COLOR_WHITE, - }),{ - + }), { + rectangle(ctx, (rect_ui_config){}, (common_ui_config){ + .point = win_point, + .size = win_size, + .background_color = 0, + .foreground_color = COLOR_WHITE, + }); }); } void draw_window(window_frame *frame){ int_point fixed_point = { global_win_offset.x + frame->x - BORDER_SIZE, global_win_offset.y + frame->y - BORDER_SIZE }; - gpu_size fixed_size = { frame->width + BORDER_SIZE*2, frame->height + BORDER_SIZE*2 }; + gpu_size fixed_size = { frame->width + BORDER_SIZE*2, frame->height + BORDER_SIZE*2 + TOOLBAR_HEIGHT }; fixed_point.x /= zoom_scale; fixed_point.y /= zoom_scale; fixed_size.width /= zoom_scale; @@ -72,7 +79,7 @@ window_frame* clicked_frame; static inline void calc_click(void *node){ window_frame* frame = (window_frame*)node; - gpu_point p = win_to_screen(frame, click_loc); + gpu_point p = win_to_screen(frame, click_loc);//TODO: account for zoom if (!p.x || !p.y) return; clicked_frame = frame; } @@ -216,6 +223,11 @@ void check_shortcuts(){ } } +void draw_menu(){ + draw_ctx *screen_ctx = gpu_get_ctx(); + fb_fill_rect(screen_ctx, 0, 0, screen_ctx->width, MENU_HEIGHT, system_theme.bg_color+0x111111); +} + int window_system(){ disable_visual(); dos_ctx = gpu_get_ctx(); @@ -292,9 +304,14 @@ int window_system(){ if (system_theme.use_desktop_zoom){ i8 scroll = get_raw_mouse_in().scroll; if (scroll){ - zoom_scale += -scroll; - zoom_scale = clamp(zoom_scale, 1, 5); - dirty_windows = true; + click_loc = get_mouse_pos(); + clicked_frame = 0; + linked_list_for_each(window_list, calc_click); + if (!clicked_frame){ + zoom_scale += -scroll; + zoom_scale = clamp(zoom_scale, 1, 5); + dirty_windows = true; + } } } disable_interrupt(); @@ -302,6 +319,7 @@ int window_system(){ active = true; draw_desktop(); linked_list_for_each(window_list, redraw_win); + draw_menu(); dirty_windows = false; } gpu_flush(); diff --git a/kernel/kernel_processes/windows/wincomp.c b/kernel/kernel_processes/windows/wincomp.c index d29f74bb..3cb761cf 100644 --- a/kernel/kernel_processes/windows/wincomp.c +++ b/kernel/kernel_processes/windows/wincomp.c @@ -10,7 +10,7 @@ int_point current_win_offset = {}; void new_managed_window(){ draw_ctx *cur = gpu_get_ctx(); if (!cur) return; - create_window(10 - current_win_offset.x, 10 - current_win_offset.y, cur->width - 20, cur->height - 20); + create_window(10 - current_win_offset.x, 10 - current_win_offset.y + MENU_HEIGHT, cur->width - 20, cur->height - 20 - MENU_HEIGHT); global_win_offset.x = current_win_offset.x; current_win_offset.x -= cur->width; } diff --git a/kernel/theme/theme.c b/kernel/theme/theme.c index c85fd39f..d00d184e 100644 --- a/kernel/theme/theme.c +++ b/kernel/theme/theme.c @@ -40,7 +40,7 @@ system_config_t system_config = { .system_name = SYSTEM_NAME, .app_directory = "boot", .use_net = false, - .preferred_screen_size = {1920,1080}, + .preferred_screen_size = { 1920,1080 }, .headless = false, .use_login = false, .use_windows = true, diff --git a/shared b/shared index fab45a86..1723042a 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit fab45a86058e1a97165ef342a32967205d11a985 +Subproject commit 1723042aba6571d1c9927349a0c60c36784dba7a diff --git a/user/terminal/main.c b/user/terminal/main.c index 47f36b57..61fa9f8c 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -357,7 +357,7 @@ int main(){ handle_input(); msleep(1); ctx.full_redraw = true; - composite(&printer_ctx, (int_point){}, 1, &ctx); + composite(&printer_ctx, (int_point){}, 1, &ctx, draw_ctx_rect(&ctx)); commit_draw_ctx(&ctx); } From 83be0be8b6f93faba64393414238ce8f0b058b91 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 24 Jul 2026 00:00:00 +0000 Subject: [PATCH 36/65] [DOS] bar shawdows --- kernel/kernel_processes/windows/dos.c | 6 ++++++ user/terminal/main.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 04c9dff1..086f0434 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -46,6 +46,11 @@ static void draw_solid_window(draw_ctx *ctx, int_point fixed_point, gpu_size fix .background_color = system_theme.bg_color + 0x111111, .foreground_color = COLOR_WHITE, }), { + rectangle(ctx, (rect_ui_config){}, (common_ui_config){ + .point = {fixed_point.x + BORDER_SIZE, fixed_point.y + TOOLBAR_HEIGHT}, + .size = {win_size.width - (BORDER_SIZE), BORDER_SIZE}, + .background_color = 0x33000000, + }); rectangle(ctx, (rect_ui_config){}, (common_ui_config){ .point = win_point, .size = win_size, @@ -226,6 +231,7 @@ void check_shortcuts(){ void draw_menu(){ draw_ctx *screen_ctx = gpu_get_ctx(); fb_fill_rect(screen_ctx, 0, 0, screen_ctx->width, MENU_HEIGHT, system_theme.bg_color+0x111111); + fb_fill_rect(screen_ctx, 0, MENU_HEIGHT-BORDER_SIZE, screen_ctx->width, BORDER_SIZE, 0x44000000); } int window_system(){ diff --git a/user/terminal/main.c b/user/terminal/main.c index 61fa9f8c..8accc21f 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -52,7 +52,7 @@ int debug_print(const char *fmt, ...){ } shell_handle* make_default_shell(shell_bindings bindings){ - return create_sheldon(bindings, 0); + return create_sheldon(bindings, 0, 0); } void clear(shell_handle *handle){ From 58c758b0aef2c5c17176e004d455ab95b6d27550 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 24 Jul 2026 00:00:00 +0000 Subject: [PATCH 37/65] [ZOOM] float zoom --- kernel/graph/tres.c | 2 +- kernel/kernel_processes/windows/dos.c | 4 ++-- shared | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/graph/tres.c b/kernel/graph/tres.c index df62f337..aea8399d 100644 --- a/kernel/graph/tres.c +++ b/kernel/graph/tres.c @@ -19,7 +19,7 @@ linked_list_t *window_list; window_frame *focused_window; -i32 zoom_scale = 1; +float zoom_scale = 1.f; uint16_t win_ids = 1; bool dirty_windows = false; diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 086f0434..854ea7c1 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -32,7 +32,7 @@ u16 paste_s = 0; static dos_mode mode; static draw_ctx *dos_ctx; -extern i32 zoom_scale; +extern float zoom_scale; static void draw_solid_window(draw_ctx *ctx, int_point fixed_point, gpu_size fixed_size, bool fill){ int_point win_point = {fixed_point.x + BORDER_SIZE, fixed_point.y + BORDER_SIZE + TOOLBAR_HEIGHT}; @@ -315,7 +315,7 @@ int window_system(){ linked_list_for_each(window_list, calc_click); if (!clicked_frame){ zoom_scale += -scroll; - zoom_scale = clamp(zoom_scale, 1, 5); + zoom_scale = clampf(zoom_scale, 1.f, 5); dirty_windows = true; } } diff --git a/shared b/shared index 1723042a..c27a5d48 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 1723042aba6571d1c9927349a0c60c36784dba7a +Subproject commit c27a5d4834330babc7e72f1484474798f5deb90c From 69abc044ede0c579a00132b2e35f110b1462c5bc Mon Sep 17 00:00:00 2001 From: di Date: Sun, 26 Jul 2026 00:00:00 +0000 Subject: [PATCH 38/65] [ZOOM] zoom in --- kernel/kernel_processes/windows/dos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 854ea7c1..5d61c55f 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -315,7 +315,7 @@ int window_system(){ linked_list_for_each(window_list, calc_click); if (!clicked_frame){ zoom_scale += -scroll; - zoom_scale = clampf(zoom_scale, 1.f, 5); + zoom_scale = clampf(zoom_scale, 0.25f, 5); dirty_windows = true; } } From 9eca4800453a685deb0aca69383f9e4e91965495 Mon Sep 17 00:00:00 2001 From: di Date: Wed, 29 Jul 2026 00:00:00 +0000 Subject: [PATCH 39/65] [DOS] desaturate window toolbar if not focused --- kernel/kernel_processes/windows/dos.c | 24 +++++++++++------------- shared | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 5d61c55f..1fc4a5e7 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -34,16 +34,23 @@ static draw_ctx *dos_ctx; extern float zoom_scale; -static void draw_solid_window(draw_ctx *ctx, int_point fixed_point, gpu_size fixed_size, bool fill){ +static void draw_solid_window(draw_ctx *ctx, int_point fixed_point, gpu_size fixed_size, bool fill, bool use_shadows, bool focused){ int_point win_point = {fixed_point.x + BORDER_SIZE, fixed_point.y + BORDER_SIZE + TOOLBAR_HEIGHT}; gpu_size win_size = {fixed_size.width - (BORDER_SIZE*2), fixed_size.height - TOOLBAR_HEIGHT - (BORDER_SIZE*2)}; + + if (use_shadows && focused) + rectangle(dos_ctx, (rect_ui_config){ + .border_size = BORDER_SIZE * 1.5, + .border_color = 0x44000000, + }, (common_ui_config){ .point = (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, .size = {fixed_size.width+BORDER_SIZE*1.5,fixed_size.height+BORDER_SIZE*1.5}, }); + DRAW(rectangle(ctx, (rect_ui_config){ .border_size = BORDER_SIZE, - .border_color = system_theme.bg_color + 0x222222 + .border_color = saturate(system_theme.bg_color + 0x222222, focused ? 0 : -90), }, (common_ui_config){ .point = fixed_point, .size = fixed_size, - .background_color = system_theme.bg_color + 0x111111, + .background_color = saturate(system_theme.bg_color + 0x111111, focused ? 0 : -90), .foreground_color = COLOR_WHITE, }), { rectangle(ctx, (rect_ui_config){}, (common_ui_config){ @@ -67,16 +74,7 @@ void draw_window(window_frame *frame){ fixed_point.y /= zoom_scale; fixed_size.width /= zoom_scale; fixed_size.height /= zoom_scale; - if (!system_theme.use_window_shadows || focused_window != frame){ - draw_solid_window(dos_ctx, (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, fixed_size, !frame->pid); - return; - } - DRAW(rectangle(dos_ctx, (rect_ui_config){ - .border_size = BORDER_SIZE * 1.5, - .border_color = 0x44000000, - }, (common_ui_config){ .point = (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, .size = {fixed_size.width+BORDER_SIZE*1.5,fixed_size.height+BORDER_SIZE*1.5}, }),{ - draw_solid_window(dos_ctx, (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, fixed_size, !frame->pid); - }); + draw_solid_window(dos_ctx, (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, fixed_size, !frame->pid, system_theme.use_window_shadows, focused_window == frame); } gpu_point click_loc; diff --git a/shared b/shared index c27a5d48..8fbb8ff9 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit c27a5d4834330babc7e72f1484474798f5deb90c +Subproject commit 8fbb8ff9e47eea097f8773bd3272cbf2d642dedc From 488b2b6051b0f996ccca138f20d8d840dd6972be Mon Sep 17 00:00:00 2001 From: di Date: Wed, 29 Jul 2026 00:00:00 +0000 Subject: [PATCH 40/65] [MENUBAR] added (cursed) central widget --- kernel/graph/tres.h | 1 + kernel/kernel_processes/windows/dos.c | 12 ++----- kernel/kernel_processes/windows/menu.c | 44 ++++++++++++++++++++++++++ kernel/kernel_processes/windows/menu.h | 3 ++ 4 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 kernel/kernel_processes/windows/menu.c create mode 100644 kernel/kernel_processes/windows/menu.h diff --git a/kernel/graph/tres.h b/kernel/graph/tres.h index 16ba8795..0a16e925 100644 --- a/kernel/graph/tres.h +++ b/kernel/graph/tres.h @@ -18,6 +18,7 @@ typedef struct { #define MENU_HEIGHT 50 #define TOOLBAR_HEIGHT 50 +#define BORDER_SIZE 3 void init_window_manager(); diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 1fc4a5e7..cb0b0740 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -14,8 +14,7 @@ #include "wincomp.h" #include "ui/color/color.h" #include "utils/cursor/cursor_manager.h" - -#define BORDER_SIZE 3 +#include "menu.h" typedef enum { right_move, left_move, down_move, up_move } dos_movement; u16 move_shortcuts[4]; @@ -225,13 +224,6 @@ void check_shortcuts(){ } } } - -void draw_menu(){ - draw_ctx *screen_ctx = gpu_get_ctx(); - fb_fill_rect(screen_ctx, 0, 0, screen_ctx->width, MENU_HEIGHT, system_theme.bg_color+0x111111); - fb_fill_rect(screen_ctx, 0, MENU_HEIGHT-BORDER_SIZE, screen_ctx->width, BORDER_SIZE, 0x44000000); -} - int window_system(){ disable_visual(); dos_ctx = gpu_get_ctx(); @@ -323,9 +315,9 @@ int window_system(){ active = true; draw_desktop(); linked_list_for_each(window_list, redraw_win); - draw_menu(); dirty_windows = false; } + draw_menu(); gpu_flush(); enable_interrupt(); if (!active && !dirty_windows && !mouse_button_pressed(LMB) && !mouse_button_pressed(MMB)) msleep(25); diff --git a/kernel/kernel_processes/windows/menu.c b/kernel/kernel_processes/windows/menu.c new file mode 100644 index 00000000..5f0f9daf --- /dev/null +++ b/kernel/kernel_processes/windows/menu.c @@ -0,0 +1,44 @@ +#include "menu.h" + +#include "graphic_types.h" +#include "graph/graphics.h" +#include "graph/tres.h" +#include "theme/theme.h" +#include "syscalls/syscalls.h" +#include "input/input_dispatch.h" + +#define draw_eye(x_off, blink, eyelid) fb_fill_rect(ctx, rect.point.x + eye_margin + x_off, rect.point.y + (rect.size.height * 0.1), eye_size.width, eye_size.height, (blink) ? eyelid : 0xFFcccccc);\ +fb_fill_rect(ctx, rect.point.x + eye_margin + p.x + x_off, rect.point.y + (rect.size.height * 0.1) + p.y, eye_size.width-pupil_distance.width, eye_size.height-pupil_distance.height, (blink) ? eyelid : 0xFF333333); + +void test_widget(draw_ctx *ctx, gpu_rect rect, color bg){ + + gpu_size eye_size = {rect.size.width * 0.2,rect.size.height * 0.3}; + i32 eye_distance = eye_size.width * 1.1; + i32 eye_margin = (rect.size.width - (eye_size.width*2 + eye_distance))/2; + + gpu_size pupil_distance = {eye_size.width*0.3,eye_size.height*0.3}; + + mouse_data data; + get_mouse_status(&data); + + gpu_point p = get_mouse_pos(); + p.x = p.x * pupil_distance.width/ctx->width; + p.y = p.y * pupil_distance.height/ctx->height; + + draw_eye(0,data.raw.buttons & 1, bg+0x111111); + draw_eye(eye_size.width + eye_distance,(data.raw.buttons >> 1) & 1, bg+0x111111); + + fb_fill_rect(ctx, rect.point.x + eye_margin, rect.size.height - eye_size.height - eye_size.height/3, rect.size.width-(eye_margin*2), eye_size.height-(get_raw_mouse_in().scroll*3), 0xFF222222); + if ((data.raw.buttons >> 2) & 1) fb_fill_rect(ctx, rect.point.x + eye_margin, rect.size.height - eye_size.height/2 - eye_size.height/3, rect.size.width-(eye_margin*2), eye_size.height/2, 0xFF442222); + +} + +void draw_menu(){ + draw_ctx *screen_ctx = gpu_get_ctx(); + fb_fill_rect(screen_ctx, 0, 0, screen_ctx->width, MENU_HEIGHT, system_theme.bg_color+0x111111); + fb_fill_rect(screen_ctx, 0, MENU_HEIGHT-BORDER_SIZE, screen_ctx->width, BORDER_SIZE, 0x44000000); + + // fb_fill_rect(screen_ctx, screen_ctx->width/2 - 100, 0, screen_ctx->width/2 + 100, MENU_HEIGHT, 0xb4dd13); + + test_widget(screen_ctx, (gpu_rect){{screen_ctx->width/2 - 100, 0}, {200, MENU_HEIGHT}},system_theme.bg_color+0x111111); +} \ No newline at end of file diff --git a/kernel/kernel_processes/windows/menu.h b/kernel/kernel_processes/windows/menu.h new file mode 100644 index 00000000..41683bbd --- /dev/null +++ b/kernel/kernel_processes/windows/menu.h @@ -0,0 +1,3 @@ +#pragma once + +void draw_menu(); \ No newline at end of file From db88dd0cbe18e2d90b3981bc23f5da44784a1b53 Mon Sep 17 00:00:00 2001 From: di Date: Wed, 29 Jul 2026 00:00:00 +0000 Subject: [PATCH 41/65] [THREADING] proper sleep process --- kernel/process/scheduler.c | 7 ++++--- kernel/process/scheduler.h | 2 +- kernel/process/syscall.c | 2 +- user/demo/default_process.c | 1 + 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 15e2fe51..ca9b5905 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -129,9 +129,10 @@ void switch_proc(ProcSwitchReason reason) { panic("No processes active", 0); thread_t *prev_t = (thread_t*)cpec; process_t *prev = current_proc, *next_proc = 0; - if (prev && prev->state == RUNNING && prev_t->state == RUNNING) { + if (prev && prev->state == RUNNING) { if (prev == idle_proc) prev->state = BLOCKED; - else enqueue_ready_thread(prev_t); + else if (prev_t->state == RUNNING) enqueue_ready_thread(prev_t); + else prev->current_thread = prev->current_thread->next ?: &prev->main_thread; } if (prev->current_thread->next){ @@ -623,7 +624,7 @@ process_t *get_all_processes(){ return process_list; } -void sleep_process(uint64_t msec){ +void sleep_thread(uint64_t msec){ irq_flags_t irq = irq_save_disable(); if (!msec) { diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index f85fbf1b..d50505c8 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -41,7 +41,7 @@ void resume_blocked_process(process_t *proc); void name_process(process_t *proc, const char *name); -void sleep_process(uint64_t msec); +void sleep_thread(uint64_t msec); void wake_processes(); bool load_process_module(process_t *p, system_module *m); diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 8cbaed62..c0d02f5a 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -180,7 +180,7 @@ u64 syscall_char_size(process_t *ctx, thread_t *current_thread){ u64 syscall_msleep(process_t *ctx, thread_t *current_thread){ syscall_depth--; - sleep_process(current_thread->PROC_X0);//TODO: sleep thread instead + sleep_thread(current_thread->PROC_X0); return 0; } diff --git a/user/demo/default_process.c b/user/demo/default_process.c index b4f3e9cf..835304ef 100644 --- a/user/demo/default_process.c +++ b/user/demo/default_process.c @@ -186,6 +186,7 @@ int copypaste(){ bool should_quit = false; bool on_quit(signal_info_t *do_not_use_this){ + msleep(3000); should_quit = true; // while (true) printl("I'm told to quit"); return true; From d907054dcd7d04b69e4cf9e4247d8b570f190129 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 42/65] [DISK] vfs mount fix --- kernel/filesystem/disk.h | 2 +- modules/disk/raspi/disk.cpp | 4 +++- modules/disk/virt/disk.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel/filesystem/disk.h b/kernel/filesystem/disk.h index 3d4748ff..5fe9584d 100644 --- a/kernel/filesystem/disk.h +++ b/kernel/filesystem/disk.h @@ -7,7 +7,7 @@ extern "C" { #include "types.h" #include "files/system_module.h" -bool init_disk_device(); +bool init_disk_device(system_module *mod); void disk_verbose(); void disk_write(const void *buffer, uint32_t sector, uint32_t count); diff --git a/modules/disk/raspi/disk.cpp b/modules/disk/raspi/disk.cpp index 26c3cd6e..2d221c4b 100644 --- a/modules/disk/raspi/disk.cpp +++ b/modules/disk/raspi/disk.cpp @@ -9,7 +9,7 @@ extern "C" void disk_verbose(){ sdhci_driver.enable_verbose(); } -extern "C" bool init_disk_device(){ +extern "C" bool init_disk_device(system_module *mod){ kprint("Initializing disk"); return sdhci_driver.init(); } @@ -26,6 +26,7 @@ system_module disk_module = (system_module){ .name = "sdhci", .mount = "disk", .version = VERSION_NUM(0, 1, 0, 0), + .owner = 0, .init = init_disk_device, .fini = 0, .open = 0, @@ -35,4 +36,5 @@ system_module disk_module = (system_module){ .truncate = 0, .getstat = 0, .readdir = 0, + .alias_info = {} }; \ No newline at end of file diff --git a/modules/disk/virt/disk.c b/modules/disk/virt/disk.c index 1fd133b4..eb7b9fe4 100644 --- a/modules/disk/virt/disk.c +++ b/modules/disk/virt/disk.c @@ -39,7 +39,7 @@ void disk_verbose(){ }\ }) -bool init_disk_device(){ +bool init_disk_device(system_module *mod){ kprint("Initializing disk"); uint64_t addr = find_pci_device(VIRTIO_VENDOR, VIRTIO_BLK_ID); if (!addr){ From 4014d43b9184007b6bd3fc0527e44f070b93425d Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 30 Jul 2026 00:00:00 +0000 Subject: [PATCH 43/65] [FS] simplify truncate to use just descriptor [USFS] close and truncate implementation --- kernel/filesystem/fat32.cpp | 13 +++++++------ kernel/filesystem/fat32.hpp | 2 +- kernel/filesystem/filesystem.c | 18 ++++++++++++------ kernel/filesystem/fsdriver.hpp | 2 +- kernel/filesystem/virtio_9p_pci.cpp | 8 ++++---- kernel/filesystem/virtio_9p_pci.hpp | 2 +- kernel/process/jobs/job_manager.h | 3 +-- shared | 2 +- 8 files changed, 28 insertions(+), 22 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index ea78b578..3ce9a314 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -505,8 +505,9 @@ size_t FAT32FS::write_file(file *descriptor, const char* buf, size_t size){ if (written) write_to_disk(mfile->serial, mfile->file_buffer.buffer, mfile->file_buffer.buffer_size); - - truncate(descriptor, mfile->file_size); + + descriptor->size = mfile->file_size; + truncate(descriptor); return written; } @@ -625,7 +626,7 @@ bool FAT32FS::stat(const char *path, fs_stat *out_stat){ return true; } -bool FAT32FS::truncate(file *descriptor, size_t size){ +bool FAT32FS::truncate(file *descriptor){ irq_flags_t irq = irq_save_disable(); module_file *mfile = (module_file*)hash_map_get(open_files, &descriptor->id, sizeof(uint64_t)); if (!mfile || !mfile->name.data) { @@ -639,7 +640,7 @@ bool FAT32FS::truncate(file *descriptor, size_t size){ if (!result.found) return false; - result.entry.filesize = size & UINT32_MAX; + result.entry.filesize = descriptor->size & UINT32_MAX; write_section_to_cluster(result.cluster,result.offset, &result.entry, sizeof(f32file_entry)); @@ -684,8 +685,8 @@ bool boot_stat(const char *path, fs_stat *out_stat){ return fs_driver->stat(path, out_stat); } -bool boot_truncate(file *descriptor, size_t size){ - return fs_driver->truncate(descriptor, size); +bool boot_truncate(file *descriptor){ + return fs_driver->truncate(descriptor); } system_module boot_fs_module = (system_module){ diff --git a/kernel/filesystem/fat32.hpp b/kernel/filesystem/fat32.hpp index ee134e28..0d7de401 100644 --- a/kernel/filesystem/fat32.hpp +++ b/kernel/filesystem/fat32.hpp @@ -95,7 +95,7 @@ class FAT32FS: public FSDriver { size_t list_contents(const char *path, void* buf, size_t size, uint64_t *offset) override; void close_file(file* descriptor) override; bool stat(const char *path, fs_stat *out_stat) override; - bool truncate(file *descriptor, size_t size) override; + bool truncate(file *descriptor) override; protected: sizedptr read_full_file(uint32_t cluster_start, uint32_t cluster_size, uint32_t cluster_count, uint64_t file_size, uint32_t root_index); void read_FAT(uint32_t location, uint32_t size, uint8_t count); diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index 02d7d49b..f2826971 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -160,9 +160,12 @@ void close_file(file *descriptor){ void close_file_global(file *descriptor, system_module *mod){ if (!mod || !mod->close) return; - if (mod->owner != get_kernel_proc()->id) - kprintf("cba rn"); - else + if (mod->owner != get_kernel_proc()->id){ + job_make(job_close, mod, { + job_serialize_fd(&app, 0, descriptor, copy_on_start); + }); + return; + } else mod->close(descriptor); } @@ -282,6 +285,7 @@ bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ job_serialize_str(&app, 0, search_path); job_serialize_stat(&app, 1, out_stat); }) + return false; } return mod->getstat(search_path, out_stat); } @@ -301,15 +305,17 @@ bool truncate(file *descriptor, size_t size){ file gfd = (file){ .id = local.mfile_id, - .size = descriptor->size, + .size = size, .cursor = descriptor->cursor, .data_type = descriptor->data_type }; if (local.mod->owner != get_kernel_proc()->id){ - kprintf("cba rn"); + job_make(job_trunc, local.mod, { + job_serialize_fd(&app, 0, &gfd, copy_on_start); + }); return false; - } else if (!local.mod->truncate(&gfd, size)) return false; + } else if (!local.mod->truncate(&gfd)) return false; descriptor->size = gfd.size; descriptor->cursor = gfd.cursor; diff --git a/kernel/filesystem/fsdriver.hpp b/kernel/filesystem/fsdriver.hpp index a11b7a36..8377d738 100644 --- a/kernel/filesystem/fsdriver.hpp +++ b/kernel/filesystem/fsdriver.hpp @@ -14,5 +14,5 @@ class FSDriver { virtual size_t list_contents(const char *path, void* buf, size_t size, file_offset *offset = 0) = 0; virtual void close_file(file* descriptor) = 0; virtual bool stat(const char *path, fs_stat *out_stat) = 0; - virtual bool truncate(file *descriptor, size_t size) = 0; + virtual bool truncate(file *descriptor) = 0; }; \ No newline at end of file diff --git a/kernel/filesystem/virtio_9p_pci.cpp b/kernel/filesystem/virtio_9p_pci.cpp index 16e84da9..f13b5718 100644 --- a/kernel/filesystem/virtio_9p_pci.cpp +++ b/kernel/filesystem/virtio_9p_pci.cpp @@ -224,11 +224,11 @@ size_t Virtio9PDriver::list_contents(const char *path, void* buf, size_t size, u return amount; } -bool Virtio9PDriver::truncate(file *descriptor, size_t size){ +bool Virtio9PDriver::truncate(file *descriptor){ module_file *mfile = (module_file*)hash_map_get(open_files, &descriptor->id, sizeof(uint64_t)); if (!mfile) return false; if (mfile->read_only) return false; - if (!set_attribute((u32)mfile->serial, P9_SETATTR_SIZE, size)) return false; + if (!set_attribute((u32)mfile->serial, P9_SETATTR_SIZE, descriptor->size)) return false; if (!sync_file(mfile)) return false; descriptor->size = mfile->file_size; if (descriptor->cursor > descriptor->size) descriptor->cursor = descriptor->size; @@ -588,8 +588,8 @@ void shared_close(file *descriptor){ p9Driver->close_file(descriptor); } -bool shared_truncate(file *descriptor, size_t size){ - return p9Driver->truncate(descriptor, size); +bool shared_truncate(file *descriptor){ + return p9Driver->truncate(descriptor); } system_module p9_fs_module = (system_module){ diff --git a/kernel/filesystem/virtio_9p_pci.hpp b/kernel/filesystem/virtio_9p_pci.hpp index 8987786b..05b1f01f 100644 --- a/kernel/filesystem/virtio_9p_pci.hpp +++ b/kernel/filesystem/virtio_9p_pci.hpp @@ -14,7 +14,7 @@ class Virtio9PDriver : public FSDriver { size_t list_contents(const char *path, void* buf, size_t size, uint64_t *offset) override; void close_file(file* descriptor) override; bool stat(const char *path, fs_stat *out_stat) override; - bool truncate(file *descriptor, size_t size) override; + bool truncate(file *descriptor) override; private: virtio_device np_dev = {}; size_t choose_version(); diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index 34def629..7ddb91df 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -3,7 +3,7 @@ #include "files/jobs.h" #include "process/process.h" -//TODO: We can probably optimize current proc fs more, but right now it blocks the entire process so we can't allow this case +//TODO: if the owner is the current process, we can downgrade the syscall into a function call without async #define job_make(job_type,mod,action)\ process_t *owner_proc = get_proc_by_pid(mod->owner);\ if (!is_privileged(owner_proc)){\ @@ -16,7 +16,6 @@ if (!is_privileged(owner_proc)){\ action\ create_new_job(app,mod);\ switch_proc(YIELD);\ - return false;\ } static inline void job_application_append_buffer(job_application_t *app, job_buffer buf){ diff --git a/shared b/shared index 8c838444..1442cef4 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 8c838444499309fcdcde2fca0fda714fa2c15074 +Subproject commit 1442cef44fcf72143332558c5f86be9f7d9f6ca6 From bf2182ee28ab18c364c971f43374dd9316c435f2 Mon Sep 17 00:00:00 2001 From: Diego Ferrari Date: Thu, 30 Jul 2026 00:00:00 +0000 Subject: [PATCH 44/65] [TERMINAL] restored cpp terminal [ENV] removed log --- kernel/process/environment/environment.c | 1 - user/UserMakefile | 8 +- user/terminal/main.c | 357 -------------------- user/terminal/main.cpp | 53 +++ user/terminal/terminal.cpp | 400 +++++++++++++++++++++++ user/terminal/terminal.hpp | 59 ++++ 6 files changed, 519 insertions(+), 359 deletions(-) delete mode 100644 user/terminal/main.c create mode 100644 user/terminal/main.cpp create mode 100644 user/terminal/terminal.cpp create mode 100644 user/terminal/terminal.hpp diff --git a/kernel/process/environment/environment.c b/kernel/process/environment/environment.c index abacf2b9..ce96e70e 100644 --- a/kernel/process/environment/environment.c +++ b/kernel/process/environment/environment.c @@ -53,7 +53,6 @@ FS_RESULT environment_open(u64 id, string_slice file_name, file *fd){ return FS_RESULT_SUCCESS; } if (slice_lit_match(file_name, "window", true)){ - print("Opening file %v",file_name); fd->id = ((env_type_win & 0xFFFF) << 16) | id; fd->data_type = DATA_WIN_SIGNATURE; fd->size = sizeof(window_info_t); diff --git a/user/UserMakefile b/user/UserMakefile index ad5c48b5..da135fa9 100644 --- a/user/UserMakefile +++ b/user/UserMakefile @@ -2,11 +2,13 @@ include ../../common.mk CPPFLAGS := -I. -I../../shared CFLAGS := $(CFLAGS_BASE) $(CPPFLAGS) +CXXFLAGS := $(CXXFLAGS_BASE) $(CPPFLAGS) LDFLAGS := -emain CLEAN_OBJS := $(shell find . -name '*.o') CLEAN_DEPS := $(shell find . -name '*.d') C_SRC := $(shell find . -name '*.c') +CPP_SRC := $(shell find . -name '*.cpp') OBJ := $(C_SRC:%.c=$(BUILD_DIR)/%.o) $(CPP_SRC:%.cpp=$(BUILD_DIR)/%.o) DEP := $(C_SRC:%.c=$(BUILD_DIR)/%.d) $(CPP_SRC:%.cpp=$(BUILD_DIR)/%.d) @@ -39,6 +41,10 @@ $(BUILD_DIR)/%.o: %.c @mkdir -p $(dir $@) $(VCC) $(CFLAGS) -c -MMD -MP $< -o $@ +$(BUILD_DIR)/%.o: %.cpp + @mkdir -p $(dir $@) + $(VCXX) $(CXXFLAGS) -c -MMD -MP $< -o $@ + clean: $(RM) $(CLEAN_OBJS) $(CLEAN_DEPS) $(TARGET) $(RM) -r $(PACKAGE) $(BUILD_DIR) @@ -46,4 +52,4 @@ clean: dump: all $(ARCH)objdump -S $(NAME).red/$(NAME).elf > dump --include $(DEP) +-include $(DEP) \ No newline at end of file diff --git a/user/terminal/main.c b/user/terminal/main.c deleted file mode 100644 index 4c24a9be..00000000 --- a/user/terminal/main.c +++ /dev/null @@ -1,357 +0,0 @@ -#include "syscalls/syscalls.h" -#include "draw/textdraw.h" -#include "shell/shell.h" -#include "shell/sheldon/sheldon.h" -#include "environment/env_types.h" -#include "data/serialize/binary_serial.h" -#include "kbd_helper.h" -#include "memory/memory.h" -#include "utils/embedded_fmt/tcf.h" -#include "files/helpers.h" -#include "header_utils/screenprinter.h" -#include "header_utils/composite.h" -#include "files/system_module.h" -#include "files/stack_fs.h" - -embedded_fmt input_format = {}; - -#define INPUT_MARGIN 10 -#define INPUT_HEIGHT (line_height+(INPUT_MARGIN*2)) - -int history_ptr = 0; -int history_count = 0; - -bool headless = false; - -bool cursor_on = false; -u64 cursor_blink_time = 500; - -u32 bg_color; - -buffer input_buf = {}; - -draw_ctx ctx = {}; - -gpu_rect screen_rect = {}; - -shell_handle* main_shell; - -void flush(shell_handle *handle, bool can_scroll); - -static char log_buf[1024]; - -int debug_print(const char *fmt, ...){ - __attribute__((aligned(16))) va_list args; - va_start(args, fmt); - memset(log_buf, 0, 1024); - size_t n = string_format_va_buf(fmt, log_buf, sizeof(log_buf), args); - va_end(args); - if (n >= sizeof(log_buf)) log_buf[sizeof(log_buf)-1] = '\0'; - printl(log_buf); - return 0; -} - -shell_handle* make_default_shell(shell_bindings bindings){ - return create_sheldon(bindings, 0, 0); -} - -void clear(shell_handle *handle){ - if (main_shell && main_shell != handle) return; - // buffer_wipe(&contents); - fb_clear(&ctx, screen_printer_formatting.current_bg_color); -} - -bool return_from_parse = false; - -void put_char(shell_handle *handle, char c){ - // print("New char %c %x %x %i",c,handle,main_shell,contents.cursor); - if (!c || (main_shell && main_shell != handle)) return; - bool render = true; - if (embedded_fmt_parse(&screen_printer_formatting, c)){ - render = false; - return_from_parse = true; - if (screen_printer_formatting.wipe){ - screen_printer_formatting.wipe = false; - clear(handle); - return; - } - } - if (!render) - return; - if (headless) - serial_transmit(c); - else { - screen_printer_put_char(c); - if (return_from_parse) flush(handle, true); - return_from_parse = false; - } -} - -void flush(shell_handle *handle, bool can_scroll){ - // print("Flush %v {%i,%i}",slice_from_buffer(&contents),rerender_range.start,rerender_range.size); - if (main_shell && main_shell != handle) return; - - screen_print_flush(can_scroll); -} - -void refresh_input(){ - fb_fill_rect(&ctx, 0, ctx.height-INPUT_HEIGHT, ctx.width, INPUT_HEIGHT, input_format.current_bg_color); - gpu_size offset = fb_draw_slice(&ctx, SLICE("> "), 0, ctx.height-INPUT_HEIGHT+INPUT_MARGIN, TEXT_SCALE, input_format.current_text_color); - fb_draw_slice(&ctx, slice_from_buffer(&input_buf), offset.width, ctx.height-INPUT_HEIGHT+INPUT_MARGIN, TEXT_SCALE, input_format.current_text_color); - if (cursor_on) - fb_fill_rect(&ctx, offset.width + (char_width * input_buf.cursor), ctx.height-INPUT_HEIGHT+INPUT_MARGIN, char_width, INPUT_HEIGHT-(INPUT_MARGIN*2), input_format.current_text_color); - commit_draw_ctx(&ctx); -} - -void bell(shell_handle *handle){ - if (main_shell && main_shell != handle) return; - print("DING"); -} - -void ascii_cmd(shell_handle *handle, char cmd, u16 proc_id){ - if (main_shell && main_shell != handle) return; - switch (cmd){ - case ASCII_CMD_ETX: - send_signal(SIG_QUIT, proc_id); - break; - case ASCII_CMD_SUB: - send_signal(SIG_STOP, proc_id); - break; - case ASCII_CMD_CAN: - send_signal(SIG_CONT, proc_id); - break; - default: break; - } -} - -void console_ctrl(shell_handle *handle, console_ctrls ctrl){ - if (main_shell && main_shell != handle) return; - switch (ctrl) { - case console_ctrl_close: halt(0); - default: break; - } -} - -void emit_data(structdef field, sizedptr data, bool is_allocated){ - // if (main_shell && main_shell != handle) return; - print("[TERMINAL implementation error] structured data displaying not implemented"); - // if (!data.ptr || !data.size) return; - // switch (field.type) { - // case binary_type_i8: print("%S: %i",field.name,*(i8*)data.ptr); break; - // case binary_type_i16: print("%S: %i",field.name,*(i16*)data.ptr); break; - // case binary_type_i32: print("%S: %i",field.name,*(i32*)data.ptr); break; - // case binary_type_i64: print("%S: %i",field.name,*(i64*)data.ptr); break; - // case binary_type_float: print("%S: %f",field.name,*(float*)data.ptr); break; - // case binary_type_double: print("%S: %f",field.name,*(double*)data.ptr); break; - // case binary_type_string: print("%S: %v",field.name,data); break; - // default: return; - // } - // if (is_allocated) release((void*)data.ptr); -} - -void flush_proxy(shell_handle *handle){ - flush(handle, true); -} - -shell_bindings terminal_bindings = (shell_bindings){ - .console_output = put_char, - .console_flush = flush_proxy, - .console_clean = clear, - .console_bell = bell, - .console_ascii_cmd = ascii_cmd, - .console_control = console_ctrl -}; - -shell_handle* create_shell(){ - shell_handle *handle = make_default_shell(terminal_bindings); - if (!handle) return 0; - return handle; -} - -bool erase(bool forward){ - if (forward && input_buf.cursor >= input_buf.buffer_size) return false; - if (!buffer_delete(&input_buf, input_buf.cursor + forward, 1)) return false; - - refresh_input(); - return true; -} - -bool run_command(){ - - bool success = false; - - screen_printer_append("\r\n"); - - write_full_file("/termhistory", input_buf.buffer, input_buf.buffer_size); - history_count++; - history_ptr = history_count; - - if (run_cmd(main_shell, slice_from_buffer(&input_buf))) success = true; - - buffer_wipe(&input_buf); - return success; -} - -bool move_buf_cursor(i64 amount){ - if (!amount) return false; - uptr old_in_c = input_buf.cursor; - if (buffer_seek(&input_buf, amount, false) == old_in_c) return false; - refresh_input(); - return true; -} - -bool scroll_history(i64 amount){ - int new_history_ptr = history_ptr + amount; - if (new_history_ptr < 0) new_history_ptr = 0; - string file = string_format("/termhistory/%i",new_history_ptr); - fs_stat st = {}; - if (statf(file.data, &st)){ - size_t hist_size = 0; - char *history = read_full_file(file.data, &hist_size); - if (input_buf.buffer) buffer_destroy(&input_buf); - input_buf = (buffer){ - .buffer = history, - .buffer_size = hist_size, - .limit = hist_size, - .options = buffer_can_grow, - .cursor = hist_size - }; - history_ptr = new_history_ptr; - return true; - } - buffer_wipe(&input_buf); - return false; -} - -void handle_mouse(){ - mouse_data data = {}; - get_mouse_status(&data); - if (data.raw.scroll){ - screen_print_scroll(data.raw.scroll, false); - } -} - -bool handle_input(){ - - handle_mouse(); - - kbd_event event; - if (!read_event(&event)) return false; - if (event.type == KEY_RELEASE) return true; - if (handle_modifier(&event)) return true; - - char key = event.key; - char readable = hid_to_char((uint8_t)key, current_modifier, special_key); - - if (key == KEY_ENTER || key == KEY_KPENTER) return run_command(); - - if (key == KEY_BACKSPACE) return erase(false); - if (key == KEY_DELETE) return erase(true); - - if (key == KEY_UP) return scroll_history(-1); - if (key == KEY_DOWN) return scroll_history(1); - - if (key == KEY_LEFT) return move_buf_cursor(-1); - if (key == KEY_RIGHT) return move_buf_cursor(1); - - if (key == KEY_PAGEDOWN || key == KEY_PAGEUP) - screen_print_scroll(key == KEY_PAGEDOWN ? -1 : 1, false); - - if (!readable) return false; - - if (!input_buf.buffer) input_buf = buffer_create(0x100, buffer_can_grow); - - buffer_write_lim(&input_buf, &readable, 1); - refresh_input(); - - flush(main_shell, true); - - return true; - -} - -void toggle_cursor(){ - cursor_on = !cursor_on; - refresh_input(); -} - -bool quit = false; - -bool termhistory_init(system_module *mod){ - printl("Mounting mod"); - // while (true) printl("I'm told to quit %i"); - return true; -} - -bool custom_stat(const char *path, fs_stat *out_stat){ - print("Stat %s into %x",path, out_stat); - stat_dir(out_stat); - return true; -} - -size_t custom_readdir(const char *path, void *buf, size_t size, file_offset *offset){ - print("READDIR %s info %x (%i) (%x)",path,buf,size,offset); - fs_dir_list_helper helper = create_dir_list_helper(buf, size); - dir_list_fill(&helper, "test"); - return dir_buf_size(&helper); -} - -system_module termhistory_mod = { - .name = "terminal history", - .mount = "termhistory", - .version = VERSION_NUM(0, 1, 0, 0), - .open = stackfs_open, - .read = stackfs_read, - .write = stackfs_write, - .readdir = custom_readdir, - .getstat = custom_stat -}; - -int main(){ - request_app_ctx(&ctx); - - screen_printer_init(dummy_draw_ctx(ctx.width, ctx.height-INPUT_HEIGHT)); - - stackfs_init(); - load_fsmodule(&termhistory_mod, true); - - u32 color_buf[2] = {}; - sreadf("/theme", &color_buf, sizeof(uint64_t)); - if ((color_buf[0] & 0xFF000000) == 0) color_buf[0] |= 0xFF000000; - if ((color_buf[1] & 0xFF000000) == 0) color_buf[1] |= 0xFF000000; - screen_printer_formatting.default_bg_color = screen_printer_formatting.current_bg_color = color_buf[0]; - screen_printer_formatting.default_text_color = screen_printer_formatting.current_text_color = color_buf[1]; - - init_tcf(&screen_printer_formatting); - - memcpy(&input_format, &screen_printer_formatting, sizeof(text_format)); - - fb_clear(&ctx, screen_printer_formatting.current_bg_color); - - main_shell = create_shell(); - - current_shell = main_shell; - - u64 cursor_current = 0; - - u64 last_time = get_time(); - refresh_input(); - while (true){ - if (quit) halt(0); - // append("Bonjour %.3i \t",i++); - u64 current_time = get_time(); - cursor_current += (current_time-last_time); - if (cursor_current >= cursor_blink_time){ - toggle_cursor(); - cursor_current = 0; - } - last_time = current_time; - handle_input(); - msleep(1); - ctx.full_redraw = true; - composite(&printer_ctx, (int_point){}, 1, &ctx, draw_ctx_rect(&ctx)); - commit_draw_ctx(&ctx); - } - - return 0; -} \ No newline at end of file diff --git a/user/terminal/main.cpp b/user/terminal/main.cpp new file mode 100644 index 00000000..f7c04074 --- /dev/null +++ b/user/terminal/main.cpp @@ -0,0 +1,53 @@ +#include "terminal.hpp" +#include "string/string.h" + +Terminal *term; + +int main(int argc, char **argv){ + term = new Terminal(); + if (argc && strncmp_case(argv[0], "headless", true, 8) == 0){ + print("Terminal in headless mode"); + term->headless = true; + } + while (1){ + term->update(); + } +} + +void term_put_char(shell_handle *handle, char c){ + if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; + if (term->headless && c) + serial_transmit(c); + else + term->put_char(c); +} + +void term_clear(shell_handle *handle){ + if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; + term->clear(); +} + +void term_flush(shell_handle *handle){ + if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; + term->refresh(); +} + +void term_bell(shell_handle *handle){ + if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; + term->bell(); +} + +void term_ascii_cmd(shell_handle *handle, char cmd, u16 proc_id){ + if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; + term->interpret_cmd_code(cmd, proc_id); +} + +void term_console_ctrl(shell_handle *handle, console_ctrls ctrl){ + if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; + term->ctrl(ctrl); +} + +void term_emit_data(structdef field, sizedptr data, bool is_allocated){ + if (!term) return; + term->emit_data(field,data,is_allocated); +} \ No newline at end of file diff --git a/user/terminal/terminal.cpp b/user/terminal/terminal.cpp new file mode 100644 index 00000000..af67631c --- /dev/null +++ b/user/terminal/terminal.cpp @@ -0,0 +1,400 @@ +#include "terminal.hpp" +#include "alloc/allocate.h" +#include "memory/memory.h" +#include "input_keycodes.h" +#include "shell/sheldon/sheldon.h" +#include "data/serialize/binary_serial.h" +#include "utils/embedded_fmt/tcf.h" + +Terminal::Terminal() : Console() { + uint32_t color_buf[2] = {}; + sreadf("/theme", &color_buf, sizeof(uint64_t)); + if ((color_buf[0] & 0xFF000000) == 0) color_buf[0] |= 0xFF000000; + current_format.default_bg_color = color_buf[0]; + current_format.current_bg_color = color_buf[0]; + current_format.default_text_color = color_buf[1]; + + char_scale = 2; + prompt_length = 2; + command_running = false; + + input_len = 0; + input_cursor = 0; + input_buf[0] = 0; + + history_len = 0; + history_index = 0; + for (uint32_t i = 0; i < history_max; i++) history[i] = nullptr; + + last_blink_ms = get_time(); + cursor_visible = true; + + dirty = false; + + term_current_shell = create_shell(); + init_tcf(¤t_format); + put_string("> "); + redraw_input_line(); + if (dirty) { + flush(dctx); + dirty = false; + } +} + +extern void term_put_char(shell_handle *handle, char c); +extern void term_clear(shell_handle *handle); +extern void term_flush(shell_handle *handle); +extern void term_bell(shell_handle *handle); +extern void term_ascii_cmd(shell_handle *handle, char cmd, u16 proc_id); +extern void term_console_ctrl(shell_handle *handle, console_ctrls ctrl); + +shell_handle* Terminal::create_shell(){ + shell_bindings terminal_bindings = (shell_bindings){ + .console_output = term_put_char, + .console_flush = term_flush, + .console_clean = term_clear, + .console_bell = term_bell, + .console_ascii_cmd = term_ascii_cmd, + .console_control = term_console_ctrl + }; + return create_sheldon(terminal_bindings, 0, 0); +} + +void Terminal::ctrl(console_ctrls ctrl){ + switch (ctrl) { + case console_ctrl_close: halt(0); + default: break; + } +} + +void Terminal::update(){ + if (!command_running) { + bool did = handle_input(); + if (!did) cursor_tick(); + } else { + end_command(); + } + + if (dirty) { + flush(dctx); + dirty = false; + } +} + +void Terminal::cursor_set_visible(bool visible){ + if (visible == cursor_visible) { + if (!visible) return; + if (last_drawn_cursor_x == (int32_t)current_format.cursor_x && last_drawn_cursor_y == (int32_t)current_format.cursor_y) return; + } + + cursor_visible = visible; + + if (last_drawn_cursor_x >= 0 && last_drawn_cursor_y >= 0) { + if ((uint32_t)last_drawn_cursor_x < columns && (uint32_t)last_drawn_cursor_y < rows) { + char *prev_line = &row_data[((scroll_row_offset + (u32)last_drawn_cursor_y) % rows) * columns]; + render_glyph(last_drawn_cursor_x*char_width, last_drawn_cursor_y * line_height, prev_line[last_drawn_cursor_x], current_format.current_text_color, current_format.current_bg_color, true); + } + last_drawn_cursor_x = -1; + last_drawn_cursor_y = -1; + } + + if (cursor_visible) { + fb_fill_rect(dctx, current_format.cursor_x * char_width, current_format.cursor_y * line_height, char_width, line_height, 0xFFFFFFFF); + last_drawn_cursor_x = (int32_t)current_format.cursor_x; + last_drawn_cursor_y = (int32_t)current_format.cursor_y; + } + + dirty = true; +} + +void Terminal::cursor_tick(){ + uint64_t now = get_time(); + if ((now - last_blink_ms) < 500) return; + last_blink_ms = now; + cursor_set_visible(!cursor_visible); +} + +void Terminal::redraw_input_line(){ + if (!check_ready()) return; + + uint32_t cw = (uint32_t)char_scale * CHAR_SIZE; + uint32_t lh = (uint32_t)char_scale * CHAR_SIZE * 2; + + fb_fill_rect(dctx, 0, current_format.cursor_y * lh, columns * cw, lh, current_format.current_bg_color); + + char* line = row_data + (((scroll_row_offset + current_format.cursor_y) % rows) * columns); + memset(line, 0, columns); + + if (columns == 0) return; + if (prompt_length >= (int)columns) return; + + line[0] = '>'; + line[1] = ' '; + + uint32_t max_input = columns - (uint32_t)prompt_length - 1; + uint32_t draw_len = input_len; + if (draw_len > max_input) draw_len = max_input; + + for (uint32_t i = 0; i < draw_len; i++) line[prompt_length + i] = input_buf[i]; + line[prompt_length + draw_len] = 0; + + uint32_t ypix = (current_format.cursor_y * lh) + (lh / 2); + fb_draw_char(dctx, 0, ypix, '>', char_scale, current_format.current_text_color); + fb_draw_char(dctx, cw, ypix, ' ', char_scale, current_format.current_text_color); + for (uint32_t i = 0; i < draw_len; i++) fb_draw_char(dctx, (prompt_length + i) * cw, ypix, input_buf[i], char_scale, current_format.current_text_color); + + if (input_cursor > draw_len) input_cursor = draw_len; + current_format.cursor_x = (uint32_t)prompt_length + input_cursor; + + last_blink_ms = get_time(); + cursor_set_visible(true); +} + +void Terminal::set_input_line(const char *s){ + input_len = 0; + input_cursor = 0; + + if (s) { + uint32_t i = 0; + while (s[i] && (i + 1) < input_max) { + input_buf[i] = s[i]; + i++; + } + input_len = i; + } + + input_buf[input_len] = 0; + input_cursor = input_len; + redraw_input_line(); +} + +void Terminal::end_command(){ + command_running = false; + if (last_char != '\r' && last_char != '\n'){ + put_char('\r'); + put_char('\n'); + } + put_string("> "); + prompt_length = 2; + + set_input_line(""); +} + +void Terminal::emit_data(structdef field, sizedptr data, bool is_allocated){ + if (!data.ptr || !data.size) return; + switch (field.type) { + case binary_type_i8: print("%S: %i",field.name,*(i8*)data.ptr); break; + case binary_type_i16: print("%S: %i",field.name,*(i16*)data.ptr); break; + case binary_type_i32: print("%S: %i",field.name,*(i32*)data.ptr); break; + case binary_type_i64: print("%S: %i",field.name,*(i64*)data.ptr); break; + case binary_type_float: print("%S: %f",field.name,*(float*)data.ptr); break; + case binary_type_double: print("%S: %f",field.name,*(double*)data.ptr); break; + case binary_type_string: print("%S: %v",field.name,data); break; + default: return; + } + if (is_allocated) release((void*)data.ptr); +} + +bool Terminal::exec_cmd(const char *cmd){ + if (!term_current_shell) return false; + + current_shell = term_current_shell; + + if (run_cmd(current_shell, slice_from_literal(cmd))) return true; + + return true; +} + +void Terminal::bell(){ + put_string("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + refresh(); +} + +void Terminal::run_command(){ + if (input_len) { + if (history_len == history_max) { + if (history[0]) release(history[0]); + for (uint32_t i = 1; i < history_max; i++) history[i - 1] = history[i]; + history_len = history_max - 1; + } + + uint32_t n = input_len; + char *copy = (char*)zalloc(n + 1); + if (copy) { + memcpy(copy, input_buf, n); + copy[n] = 0; + history[history_len++] = copy; + } + } + history_index = history_len; + + put_char('\r'); + put_char('\n'); + + const char* fullcmd = input_buf; + while (*fullcmd == ' ' || *fullcmd == '\t') fullcmd++; + + if (*fullcmd == 0) { + command_running = true; + return; + } + + if (!exec_cmd(fullcmd)){ + const char *next = seek_to(fullcmd, ' '); + size_t len = next - fullcmd - (next && *(next-1) == ' ' ? 1 : 0); + string_slice cmd = (string_slice){ .data = (char*)fullcmd, .length = len }; + if (slice_lit_match(cmd, "exit", true) || slice_lit_match(cmd, "q", true)){ + halt(0); + } else { + string s = string_format("Unknown command %v", cmd); + put_string(s.data); + string_free(s); + } + } + + command_running = true; +} + +bool Terminal::interpret_cmd_code(char code, u16 proc){ + if (code == ASCII_CMD_ETX){ + send_signal(SIG_QUIT, proc); + return true; + } + if (code == ASCII_CMD_SUB){ + send_signal(SIG_STOP, proc); + return true; + } + if (code == ASCII_CMD_CAN){ + send_signal(SIG_CONT, proc); + } + return false; +} + +bool Terminal::handle_input(){ + kbd_event event; + if (!read_event(&event)) return false; + if (event.type == KEY_RELEASE) return true; + if (event.type != KEY_PRESS) return handle_modifier(&event); + + char key = event.key; + char readable = hid_to_char((uint8_t)key, current_modifier, special_key); + + if (command_running){ + return interpret_cmd_code(readable, 0); + } + + if (key == KEY_ENTER || key == KEY_KPENTER){ + run_command(); + return true; + } + + if (key == KEY_LEFT) { + if (input_cursor) input_cursor--; + current_format.cursor_x = (uint32_t)prompt_length + input_cursor; + last_blink_ms = get_time(); + cursor_set_visible(true); + return true; + } + + if (key == KEY_RIGHT) { + if (input_cursor < input_len) input_cursor++; + current_format.cursor_x = (uint32_t)prompt_length + input_cursor; + last_blink_ms = get_time(); + cursor_set_visible(true); + return true; + } + + if (key == KEY_UP) { + if (history_len && history_index) { + history_index--; + set_input_line(history[history_index]); + } + return true; + } + + if (key == KEY_DOWN) { + if (history_len) { + if (history_index + 1 < history_len) { + history_index++; + set_input_line(history[history_index]); + } else { + history_index = history_len; + set_input_line(""); + } + } + return true; + } + + if (key == KEY_BACKSPACE){ + if (!input_cursor) return true; + for (uint32_t i = input_cursor; i < input_len; i++) input_buf[i - 1] = input_buf[i]; + input_len--; + input_cursor--; + input_buf[input_len] = 0; + redraw_input_line(); + return true; + } + + if (key == KEY_DELETE) { + if (input_cursor >= input_len) return true; + for (uint32_t i = input_cursor + 1; i <= input_len; i++) input_buf[i - 1] = input_buf[i]; + input_len--; + redraw_input_line(); + return true; + } + + if (!readable) return true; + + uint32_t max_visible = 0; + if (columns > (uint32_t)prompt_length + 1) max_visible = columns - (uint32_t)prompt_length - 1; + if (input_len >= input_max - 1) return true; + if (max_visible && input_len >= max_visible) return true; + + for (uint32_t i = input_len; i > input_cursor; i--) input_buf[i] = input_buf[i - 1]; + input_buf[input_cursor] = readable; + input_len++; + input_cursor++; + input_buf[input_len] = 0; + redraw_input_line(); + return true; +} + +draw_ctx* Terminal::get_ctx(){ + if (dctx) release(dctx); + draw_ctx *ctx = (draw_ctx*)zalloc(sizeof(draw_ctx)); + if (!ctx) return nullptr; + request_draw_ctx(ctx); + return ctx; +} + +void Terminal::put_char(char c){ + if (headless){ + serial_transmit(c); + return; + } + Console::put_char(c); +} + +void Terminal::put_slice(string_slice slice){ + if (!check_ready()) return; + for (u32 i = 0; i < slice.length; i++) Terminal::put_char(slice.data[i]); + flush(dctx); +} + +void Terminal::put_string(const char* str){ + Terminal::put_slice(slice_from_literal(str)); +} + +void Terminal::flush(draw_ctx *ctx){ + if (headless) return; + commit_draw_ctx(ctx); +} + +void Terminal::refresh(){ + if (headless) return; + flush(dctx); +} + +bool Terminal::screen_ready(){ + return !headless; +} \ No newline at end of file diff --git a/user/terminal/terminal.hpp b/user/terminal/terminal.hpp new file mode 100644 index 00000000..a0f6cd86 --- /dev/null +++ b/user/terminal/terminal.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include "utils/console.hpp" +#include "shell/shell.h" +#include "kbd_helper.h" +#include "environment/env_types.h" +#include "data/serialize/binary_serial.h" + +class Terminal: public Console { +public: + Terminal(); + void update(); + shell_handle *term_current_shell; + void emit_data(structdef, sizedptr, bool); + void refresh(); + void bell(); + bool interpret_cmd_code(char code, u16 proc); + void ctrl(console_ctrls ctrl); + void put_char(char c) override; + void put_string(const char* str) override; + void put_slice(string_slice slice) override; + bool headless; +protected: + bool handle_input(); + void repeat_tick(); + void end_command(); + int prompt_length; + void run_command(); + + void redraw_input_line(); + void set_input_line(const char *s); + void cursor_tick(); + void cursor_set_visible(bool visible); + + bool exec_cmd(const char *cmd); + + draw_ctx* get_ctx() override; + void flush(draw_ctx *ctx) override; + bool screen_ready() override; + + shell_handle* create_shell(); + + bool command_running; + + static constexpr uint32_t input_max = 1024; + char input_buf[input_max]; + uint32_t input_len; + uint32_t input_cursor; + + static constexpr uint32_t history_max = 32; + char *history[history_max]; + uint32_t history_len; + uint32_t history_index; + + uint64_t last_blink_ms; + bool cursor_visible; + + bool dirty; +}; \ No newline at end of file From 8bd4fd2061cabfea26d36af1b11a261f129877d5 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 31 Jul 2026 00:00:00 +0000 Subject: [PATCH 45/65] [SIGNAL] defaults for non-immediates [DOS, WIP] close window button (disabled due to scheduler bug) [DOS] close window separate from focus logic --- kernel/graph/tres.c | 18 +++++++++++++++--- kernel/graph/tres.h | 2 ++ kernel/input/input_dispatch.c | 20 +++++++++++--------- kernel/input/input_dispatch.h | 1 + kernel/kernel_processes/windows/dos.c | 22 +++++++++++++++++++--- kernel/process/scheduler.c | 3 +++ kernel/process/signals/signals.c | 6 ++++++ shared | 2 +- user/demo/default_process.c | 7 +++++-- 9 files changed, 63 insertions(+), 18 deletions(-) diff --git a/kernel/graph/tres.c b/kernel/graph/tres.c index aea8399d..5ec5f945 100644 --- a/kernel/graph/tres.c +++ b/kernel/graph/tres.c @@ -53,8 +53,11 @@ gpu_point win_to_screen(window_frame *frame, gpu_point point){ return (gpu_point){}; } +extern process_t *win_system_proc; + gpu_point convert_mouse_position(gpu_point point){ process_t *p = get_current_proc(); + if (p == win_system_proc) return point; linked_list_node_t *node = linked_list_find(window_list, PHYS_TO_VIRT_P(&p->win_id), PHYS_TO_VIRT_P(find_window)); if (node && node->data){ window_frame* frame = (window_frame*)node->data; @@ -280,7 +283,14 @@ void commit_frame(draw_ctx* frame_ctx, window_frame* frame, bool overwrite_focus frame_ctx->dirty_count = 0; frame_ctx->full_redraw = false; - +} + +void window_close_process(process_t *proc){ + u16 npid = proc && proc->win_id ? window_fallback_focus(proc->win_id, proc->id) : 0; + if (npid){ + process_t *next = get_proc_by_pid(npid); + if (next && next->focused && next->state != STOPPED && next->id && next->main_thread.pc && next->main_thread.sp && (is_privileged(next) || next->mm.ttbr0)) sys_set_focus(next->id); + } } u16 window_fallback_focus(u16 win_id, u16 skip_id){ @@ -290,8 +300,10 @@ u16 window_fallback_focus(u16 win_id, u16 skip_id){ window_frame *frame = node->data; if (frame->pid != skip_id){ process_t *proc = get_proc_by_pid(frame->pid); - proc->focused = true; - return frame->pid; + if (proc){ + proc->focused = true; + return frame->pid; + } } process_t *proc = get_all_processes(); diff --git a/kernel/graph/tres.h b/kernel/graph/tres.h index 0a16e925..7bb126cd 100644 --- a/kernel/graph/tres.h +++ b/kernel/graph/tres.h @@ -3,6 +3,7 @@ #include "types.h" #include "ui/draw/draw.h" #include "data/struct/linked_list.h" +#include "process/process.h" #ifdef __cplusplus extern "C" { @@ -35,6 +36,7 @@ void commit_frame(draw_ctx* frame_ctx, window_frame* frame, bool overwrite_focus u16 window_fallback_focus(u16 win_id, u16 skip_id); void set_window_focus(uint16_t win_id); void unset_window_focus(); +void window_close_process(process_t *proc); gpu_point convert_mouse_position(gpu_point p); diff --git a/kernel/input/input_dispatch.c b/kernel/input/input_dispatch.c index 4752f0b9..194c4e8f 100644 --- a/kernel/input/input_dispatch.c +++ b/kernel/input/input_dispatch.c @@ -151,6 +151,10 @@ bool mouse_button_pressed(int mb){ return (last_cursor_state & (1 << mb)) == (1 << mb); } +bool mouse_any_button_pressed(){ + return last_cursor_state; +} + uint16_t sys_subscribe_shortcut_current(keypress kp){ return sys_subscribe_shortcut(get_current_proc_pid(),kp); } @@ -184,16 +188,14 @@ void sys_set_focus(int pid){ void sys_unset_focus(bool close){ process_t *proc = focused_proc; - if (proc) proc->focused = false; - focused_proc = 0; - if (system_config.use_windows) unset_window_focus(); - - u16 npid = proc && proc->win_id ? window_fallback_focus(proc->win_id, proc->id) : 0; - if (npid) - { - process_t *next = get_proc_by_pid(npid); - if (next && next->focused && next->state != STOPPED && next->id && next->main_thread.pc && next->main_thread.sp && (is_privileged(next) || next->mm.ttbr0)) focused_proc = next; + if (!proc) return; + if (proc->focused){ + proc->focused = false; + focused_proc = 0; + if (system_config.use_windows) unset_window_focus(); } + + window_close_process(proc); } u16 sys_get_focused_pid(){ diff --git a/kernel/input/input_dispatch.h b/kernel/input/input_dispatch.h index 129105f2..47fd04cf 100644 --- a/kernel/input/input_dispatch.h +++ b/kernel/input/input_dispatch.h @@ -18,6 +18,7 @@ mouse_input get_raw_mouse_in(); gpu_point get_mouse_pos(); bool mouse_button_pressed(int mb); +bool mouse_any_button_pressed(); uint16_t sys_subscribe_shortcut(uint16_t pid, keypress kp); uint16_t sys_subscribe_shortcut_current(keypress kp); diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index cb0b0740..2025ffa1 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -33,7 +33,7 @@ static draw_ctx *dos_ctx; extern float zoom_scale; -static void draw_solid_window(draw_ctx *ctx, int_point fixed_point, gpu_size fixed_size, bool fill, bool use_shadows, bool focused){ +static void draw_solid_window(window_frame *frame, draw_ctx *ctx, int_point fixed_point, gpu_size fixed_size, bool fill, bool use_shadows, bool focused){ int_point win_point = {fixed_point.x + BORDER_SIZE, fixed_point.y + BORDER_SIZE + TOOLBAR_HEIGHT}; gpu_size win_size = {fixed_size.width - (BORDER_SIZE*2), fixed_size.height - TOOLBAR_HEIGHT - (BORDER_SIZE*2)}; @@ -52,6 +52,17 @@ static void draw_solid_window(draw_ctx *ctx, int_point fixed_point, gpu_size fix .background_color = saturate(system_theme.bg_color + 0x111111, focused ? 0 : -90), .foreground_color = COLOR_WHITE, }), { + #if false + bool close_pressed = false; + button(ctx, (rect_ui_config){}, (common_ui_config){ + .point = RELATIVE(parent.size.width - (BORDER_SIZE * 2) - 40 - BORDER_SIZE,BORDER_SIZE), + .size = {30, 30}, + .background_color = 0xFFB40000, + }, &close_pressed); + if (close_pressed){ + send_signal(SIG_QUIT, frame->pid); + } + #endif rectangle(ctx, (rect_ui_config){}, (common_ui_config){ .point = {fixed_point.x + BORDER_SIZE, fixed_point.y + TOOLBAR_HEIGHT}, .size = {win_size.width - (BORDER_SIZE), BORDER_SIZE}, @@ -73,7 +84,7 @@ void draw_window(window_frame *frame){ fixed_point.y /= zoom_scale; fixed_size.width /= zoom_scale; fixed_size.height /= zoom_scale; - draw_solid_window(dos_ctx, (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, fixed_size, !frame->pid, system_theme.use_window_shadows, focused_window == frame); + draw_solid_window(frame, dos_ctx, (int_point){(uint32_t)fixed_point.x,(uint32_t)fixed_point.y}, fixed_size, !frame->pid, system_theme.use_window_shadows, focused_window == frame); } gpu_point click_loc; @@ -311,6 +322,7 @@ int window_system(){ } } disable_interrupt(); + if (mouse_any_button_pressed()) dirty_windows = true; if (dirty_windows){ active = true; draw_desktop(); @@ -325,6 +337,10 @@ int window_system(){ return 0; } +process_t *win_system_proc; + process_t* create_windowing_system(){ - return create_kernel_process("dos", window_system, 0, 0); + if (!win_system_proc) + win_system_proc = create_kernel_process("dos", window_system, 0, 0); + return win_system_proc; } diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index ca9b5905..95d47bc7 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -21,6 +21,7 @@ #include "alloc/allocate.h" #include "files/dir_list.h" #include "stack_manager.h" +#include "graph/tres.h" extern void save_pc_interrupt(uintptr_t ptr); extern void restore_context(uintptr_t ptr); @@ -588,6 +589,8 @@ void stop_process(uint16_t pid, int32_t exit_code){ if (proc->focused) sys_unset_focus(false); + else + window_close_process(proc); remove_sleeping_process(proc, pid); update_sleep_timer(); diff --git a/kernel/process/signals/signals.c b/kernel/process/signals/signals.c index c365b437..e42b54db 100644 --- a/kernel/process/signals/signals.c +++ b/kernel/process/signals/signals.c @@ -33,6 +33,12 @@ bool send_signal_proc_proc(signal_types type, i64 value, process_t *source, proc thread_t *t = &destination->signal_handlers[type]; if (t->pc) schedule_thread(destination,t); + else + handle_signal_default(destination, &(signal_info_t){ + .sender = source->id, + .type = type, + .value = value, + }); switch_proc(YIELD); diff --git a/shared b/shared index 8fbb8ff9..4c6c12c5 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 8fbb8ff9e47eea097f8773bd3272cbf2d642dedc +Subproject commit 4c6c12c5f152a9d037c733e1476e8a1d1503e104 diff --git a/user/demo/default_process.c b/user/demo/default_process.c index 835304ef..ebf8b94c 100644 --- a/user/demo/default_process.c +++ b/user/demo/default_process.c @@ -205,7 +205,7 @@ struct { char* name; int (*fn)(); } demos[] = { int main(int argc, char* argv[]){ handle_signal(SIG_QUIT, on_quit); - send_signal(SIG_QUIT, 7); + // send_signal(SIG_QUIT, 7);//TODO: get own procid? request_draw_ctx(&ctx); @@ -244,8 +244,11 @@ int main(int argc, char* argv[]){ if (ev.type == KEY_PRESS){ if (ev.key >= KEY_1 && ev.key <= (KEY_1 + count - 1)){ int index = ev.key - KEY_1; - if (index >= 0 && index < count) + if (index >= 0 && index < count){ + fb_clear(&ctx, 0); + commit_draw_ctx(&ctx); return demos[index].fn(); + } } if (ev.key == KEY_ESC) halt(0); } From 3a3bef3ef4e800319cabe264636aa8778a710bb2 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 31 Jul 2026 00:00:00 +0000 Subject: [PATCH 46/65] [SCHEDULER] properly skip resettable processes [DOS] restored close button --- kernel/kernel_processes/windows/dos.c | 4 +--- kernel/process/scheduler.c | 6 +++++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 2025ffa1..f19094f8 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -51,8 +51,7 @@ static void draw_solid_window(window_frame *frame, draw_ctx *ctx, int_point fixe .size = fixed_size, .background_color = saturate(system_theme.bg_color + 0x111111, focused ? 0 : -90), .foreground_color = COLOR_WHITE, - }), { - #if false + }), { bool close_pressed = false; button(ctx, (rect_ui_config){}, (common_ui_config){ .point = RELATIVE(parent.size.width - (BORDER_SIZE * 2) - 40 - BORDER_SIZE,BORDER_SIZE), @@ -62,7 +61,6 @@ static void draw_solid_window(window_frame *frame, draw_ctx *ctx, int_point fixe if (close_pressed){ send_signal(SIG_QUIT, frame->pid); } - #endif rectangle(ctx, (rect_ui_config){}, (common_ui_config){ .point = {fixed_point.x + BORDER_SIZE, fixed_point.y + TOOLBAR_HEIGHT}, .size = {win_size.width - (BORDER_SIZE), BORDER_SIZE}, diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 95d47bc7..17b0c7e5 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -148,12 +148,16 @@ void switch_proc(ProcSwitchReason reason) { if (queued->state != READY) continue; process_t *proc = get_proc_by_pid(queued->pid); next_proc = (process_t*)proc; + if (!process_can_run(next_proc)) continue; break; } } if (!next_proc && current_proc && current_proc != idle_proc && current_proc->state == RUNNING && process_can_run(current_proc)) next_proc = current_proc; - if (!next_proc) next_proc = idle_proc; + if (!next_proc || !process_can_run(next_proc)) { + next_proc = idle_proc; + print("Selected idle proc %llx",next_proc); + } if (!next_proc || !process_can_run(next_proc)) panic("no runnable process", 0); //if (next_proc == idle_proc && prev != idle_proc) kprint("entering idle"); From fd741f91cdb34f466373cdd1f7321ec82ad86cbb Mon Sep 17 00:00:00 2001 From: di Date: Fri, 31 Jul 2026 00:00:00 +0000 Subject: [PATCH 47/65] [PFS] multi-module loading support --- kernel/filesystem/filesystem.c | 6 ++--- kernel/filesystem/modules/fs_isolation.c | 5 ++++ kernel/filesystem/modules/fs_isolation.h | 1 + kernel/filesystem/modules/module_loader.c | 9 +++++-- kernel/process/jobs/job_manager.c | 29 ++++++++++++----------- kernel/process/jobs/job_manager.h | 6 ++--- kernel/process/kernel_syscall_impl.c | 2 +- kernel/process/process.h | 4 ++-- kernel/process/scheduler.c | 16 ++++++++----- kernel/process/syscall.c | 3 ++- 10 files changed, 49 insertions(+), 32 deletions(-) diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index ba4a38c4..29b5ee11 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -56,7 +56,7 @@ FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor if (!mod->open) return FS_RESULT_NOTFOUND; FS_RESULT result = FS_RESULT_DRIVER_ERROR; if (mod->owner != get_kernel_proc()->id){ - job_make(job_open, { + job_make(job_open, mod, { job_serialize_str(&app, 0, path); job_serialize_fd(&app, 1, descriptor, copy_on_end); }); @@ -248,7 +248,7 @@ size_t list_directory_contents(module_root *root, const char *path, void* buf, s } if (!mod->readdir) return 0; if (mod->owner != get_kernel_proc()->id){ - job_make(job_readdir, { + job_make(job_readdir, mod, { job_serialize_str(&app, 0, search_path); job_serialize_buf(&app, 1, true, buf, size, copy_on_end); job_serialize_off(&app, 3, offset); @@ -272,7 +272,7 @@ bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ } if (!mod->getstat) return false; if (mod->owner != get_kernel_proc()->id){ - job_make(job_stat, { + job_make(job_stat, mod, { job_serialize_str(&app, 0, search_path); job_serialize_stat(&app, 1, out_stat); }) diff --git a/kernel/filesystem/modules/fs_isolation.c b/kernel/filesystem/modules/fs_isolation.c index 970d0227..03dd1dbc 100644 --- a/kernel/filesystem/modules/fs_isolation.c +++ b/kernel/filesystem/modules/fs_isolation.c @@ -66,4 +66,9 @@ string resolve_isolated_path(const char *path, u64 id, module_root *resolved, bo } memcpy(resolved,localfs,sizeof(module_root)); return string_from_literal(path); +} + +void destroy_fs(u64 fsid){ + if (!fsid) return; + //TODO: STUB } \ No newline at end of file diff --git a/kernel/filesystem/modules/fs_isolation.h b/kernel/filesystem/modules/fs_isolation.h index 30bb99b9..3e4a29cb 100644 --- a/kernel/filesystem/modules/fs_isolation.h +++ b/kernel/filesystem/modules/fs_isolation.h @@ -21,6 +21,7 @@ size_t list_root(void* buf, size_t size, uint64_t *offset); //Userland string resolve_isolated_path(const char *path, u64 id, module_root *resolved, bool allow_kfs); +void destroy_fs(u64 fsid); #ifdef __cplusplus } diff --git a/kernel/filesystem/modules/module_loader.c b/kernel/filesystem/modules/module_loader.c index 09e3bf43..6e77bf50 100644 --- a/kernel/filesystem/modules/module_loader.c +++ b/kernel/filesystem/modules/module_loader.c @@ -32,12 +32,17 @@ bool load_module_to(hash_map_t* modules, system_module *module){ } if (!module->version){ string format = string_format("Version number cannot be null for module /%s",module->mount); - if (strcmp(module->mount,"/console")) + if (strcmp(module->mount,"/console")) { #ifdef MODULE_STRICT - panic(format.data,0); + if (module->owner != get_kernel_proc()->id){ + kprintf(format.data); + } else { + panic(format.data,0); + } #else kprintf(format.data); #endif + } string_free(format); return false; } diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index e93d7dda..bff4fd8d 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -16,6 +16,7 @@ typedef struct { job_buffer buffers[8]; size_t buffer_count; job_types type; + system_module *mod; } job_state_t; linked_list_t *job_list; @@ -35,13 +36,13 @@ job_state_t* job_alloc(){ return job; } -bool prepare_thread(job_state_t *job, job_application_t application, process_t *proc, thread_t *t){ +bool prepare_thread(job_state_t *job, system_module *mod, job_application_t application, process_t *proc, thread_t *t){ uptr entry = 0; switch (application.type){ - case job_stat: entry = (uptr)proc->exposed_fs.getstat; break; - case job_readdir: entry = (uptr)proc->exposed_fs.readdir; break; - case job_open: entry = (uptr)proc->exposed_fs.open; break; - case job_close: entry = (uptr)proc->exposed_fs.close; break; + case job_stat: entry = (uptr)mod->getstat; break; + case job_readdir: entry = (uptr)mod->readdir; break; + case job_open: entry = (uptr)mod->open; break; + case job_close: entry = (uptr)mod->close; break; default: return false; } if (!entry) return false; @@ -75,19 +76,20 @@ bool prepare_thread(job_state_t *job, job_application_t application, process_t * return true; } -job_id_t create_new_job(job_application_t application){ - job_state_t *job = job_alloc(); - job->type = application.type; +job_id_t create_new_job(job_application_t application, system_module *mod){ process_t *requesting_proc = get_proc_by_pid(application.requesting_pid); if (!requesting_proc){ print("[JOB error] Unknown requesting proc %i",application.requesting_pid); } + job_state_t *job = job_alloc(); + job->type = application.type; + job->mod = mod; thread_t *requester = (thread_t*)get_thread_from_proc(requesting_proc, application.requesting_tid); job->requester = requester; process_t *fs_owner = get_proc_by_pid(application.worker_pid); - print("[JOB debug] Sync between %i - %i will happen with job %i - %i",requester->pid,application.worker_pid,job->id,application.type); thread_t *new_t = alloc_thread(); - if (!prepare_thread(job, application, fs_owner, new_t)) return false; + if (!prepare_thread(job, mod, application, fs_owner, new_t)) return false; + print("[JOB debug] Sync between %i - %i will happen with job %i of type %i using thread %i",requester->pid,application.worker_pid,job->id,application.type,new_t->tid); new_t->job_id = job->id; job->worker = new_t; requester->state = BLOCKED; @@ -128,7 +130,6 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ return; } process_t *proc = get_proc_by_pid(st->requester->pid); - process_t *fsproc = get_proc_by_pid(st->worker->pid); // if (st->type == job_open){ // process_t *fsproc = get_proc_by_pid(st->worker->pid); // if (fsproc){ @@ -136,7 +137,7 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ // instance_local_fd(&fsproc->exposed_fs, fd); // } // } - st->requester->state = RUNNING;//TODO: schedule once the scheduler is fully thread-based + ready_thread(st->requester); proc->state = RUNNING;//TODO: this shouldn't be necessary ready_process(proc); st->requester->PROC_X0 = ret; @@ -151,10 +152,10 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ if (buf.fd){ print("[JOB DEBUG] fd %i size %i signature %s",fd->id,fd->size,&fd->data_type); if (st->type == job_open){ - instance_local_fd(&fsproc->exposed_fs, addr); + instance_local_fd(st->mod, addr); } } } } - print("[JOB] %i fulfilled",job_id); + print("[JOB] %i fulfilled by %i",job_id,thread->tid); } \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index 68930271..b779a497 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -4,7 +4,7 @@ #include "process/process.h" //TODO: We can probably optimize current proc fs more, but right now it blocks the entire process so we can't allow this case -#define job_make(job_type,action)\ +#define job_make(job_type,mod,action)\ if (get_current_proc()->id == mod->owner){\ return false;\ }\ @@ -17,7 +17,7 @@ if (!is_privileged(owner_proc)){\ .type = job_type\ };\ action\ - create_new_job(app);\ + create_new_job(app,mod);\ switch_proc(YIELD);\ return false;\ } @@ -84,5 +84,5 @@ static inline void job_serialize_off(job_application_t *application, int arg_num job_application_append_buffer(application, buf); } -job_id_t create_new_job(job_application_t application); +job_id_t create_new_job(job_application_t application, system_module *mod); void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread); diff --git a/kernel/process/kernel_syscall_impl.c b/kernel/process/kernel_syscall_impl.c index 33d3c694..5f7324ea 100644 --- a/kernel/process/kernel_syscall_impl.c +++ b/kernel/process/kernel_syscall_impl.c @@ -125,7 +125,7 @@ int32_t socket_close(SocketHandle *handle){ FS_RESULT openf(const char* path, file* descriptor){ module_root rootfs = {}; string s = resolve_isolated_path(path, get_current_proc()->permissions.fs_id, &rootfs, true); - if (!s.data || !s.length) return open_file(kernel_fs(), path, descriptor);; + if (!s.data || !s.length) return open_file(kernel_fs(), path, descriptor); FS_RESULT res = open_file(&rootfs, s.data, descriptor); string_free(s); return res; diff --git a/kernel/process/process.h b/kernel/process/process.h index 9c10534d..63dea750 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -53,7 +53,8 @@ typedef struct { } signal_buffer_t; typedef struct { - u64 fs_id; + u64 fs_id;//Filesystem this process has access to + u64 owned_fs_id;//Filesystem this process owns, not automapped to fs_id due to isolation not being enforced yet } system_permissions; typedef enum { STOPPED, READY, RUNNING, BLOCKED, SLEEPING } process_state; @@ -116,7 +117,6 @@ struct process_t { char name[MAX_PROC_NAME_LENGTH]; sizedptr debug_lines; sizedptr debug_line_str; - system_module exposed_fs; thread_t fs_thread; mm_struct mm; int thread_count; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 17b0c7e5..6e43bf9b 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -740,10 +740,14 @@ thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point return addr; } -bool load_process_module(process_t *p, system_module *m){ - p->exposed_fs = *m; - p->exposed_fs.name = string_from_literal(p->exposed_fs.name).data; - p->exposed_fs.mount = string_from_literal(p->exposed_fs.mount).data; - p->exposed_fs.owner = p->id; - return load_module(&p->exposed_fs); +bool load_process_module(process_t *p, system_module *m){//TODO: this doesn't belong here + if (!p->permissions.owned_fs_id) p->permissions.owned_fs_id = register_fs_id(); + module_root *root = get_fs_for_id(p->permissions.fs_id); + system_module *mod = zalloc(sizeof(system_module)); + memcpy(mod, m, sizeof(system_module)); + mod->name = string_from_literal(m->name).data; + mod->mount = string_from_literal(m->mount).data; + mod->owner = p->id; + load_module_to(root, mod); + return load_module(mod); } diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index c0d02f5a..b06ef239 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -489,7 +489,8 @@ uint64_t syscall_load_fsmod(process_t *ctx, thread_t *current_thread){ } uint64_t syscall_unload_fsmod(process_t *ctx, thread_t *current_thread){ - return unload_module(&ctx->exposed_fs); + //TODO: this syscall needs to be remade with the specific module + return 0; } u64 syscall_in_case_of_js(process_t *ctx, thread_t *current_thread){ From 49e8a376f249a248f3e7acf9c3477be940562ca1 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 31 Jul 2026 00:00:00 +0000 Subject: [PATCH 48/65] [THREADING] use queue for threads instead of current --- kernel/process/jobs/job_manager.c | 9 --- kernel/process/jobs/job_manager.h | 2 +- kernel/process/process.h | 1 - kernel/process/scheduler.c | 92 ++++++++++--------------------- kernel/process/scheduler.h | 2 +- kernel/process/syscall.c | 1 - 6 files changed, 32 insertions(+), 75 deletions(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index bff4fd8d..b1fd5bdd 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -130,16 +130,7 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ return; } process_t *proc = get_proc_by_pid(st->requester->pid); - // if (st->type == job_open){ - // process_t *fsproc = get_proc_by_pid(st->worker->pid); - // if (fsproc){ - // file* fd = quick_translate(st->requester, proc, (uptr)st->fd); - // instance_local_fd(&fsproc->exposed_fs, fd); - // } - // } ready_thread(st->requester); - proc->state = RUNNING;//TODO: this shouldn't be necessary - ready_process(proc); st->requester->PROC_X0 = ret; for (size_t i = 0; i < st->buffer_count; i++){ job_buffer buf = st->buffers[i]; diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index b779a497..fe572812 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -12,7 +12,7 @@ process_t *owner_proc = get_proc_by_pid(mod->owner);\ if (!is_privileged(owner_proc)){\ job_application_t app = (job_application_t){\ .requesting_pid = get_current_proc()->id,\ - .requesting_tid = get_current_proc()->current_thread->tid,\ + .requesting_tid = get_current_thread()->tid,\ .worker_pid = owner_proc->id,\ .type = job_type\ };\ diff --git a/kernel/process/process.h b/kernel/process/process.h index 63dea750..9a6f5ec3 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -83,7 +83,6 @@ struct thread_t { struct process_t { thread_t main_thread; uint16_t id; - thread_t *current_thread; bool suspended; paddr_t heap_phys; kaddr_t output; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 6e43bf9b..10b54536 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -10,7 +10,6 @@ #include "data/struct/queue.h" #include "data/struct/linked_list.h" #include "std/memory.h" -#include "math/math.h" #include "memory/mmu.h" #include "process/syscall.h" #include "memory/addr.h" @@ -133,39 +132,37 @@ void switch_proc(ProcSwitchReason reason) { if (prev && prev->state == RUNNING) { if (prev == idle_proc) prev->state = BLOCKED; else if (prev_t->state == RUNNING) enqueue_ready_thread(prev_t); - else prev->current_thread = prev->current_thread->next ?: &prev->main_thread; } - if (prev->current_thread->next){ - do { - prev->current_thread = prev->current_thread->next; - } while (prev->current_thread && prev->current_thread->state != RUNNING && prev->current_thread->state != READY); - } else { - while (!cqueue_is_empty(&ready_queue)) { - thread_t *queued = 0; - if (!cqueue_dequeue(&ready_queue, &queued)) break; - if (!queued) continue; - if (queued->state != READY) continue; - process_t *proc = get_proc_by_pid(queued->pid); - next_proc = (process_t*)proc; - if (!process_can_run(next_proc)) continue; - break; - } + + thread_t *next_thread = 0; + while (!cqueue_is_empty(&ready_queue)) { + thread_t *queued = 0; + if (!cqueue_dequeue(&ready_queue, &queued)) break; + if (!queued) continue; + if (queued->state != READY) continue; + process_t *proc = get_proc_by_pid(queued->pid); + next_proc = (process_t*)proc; + next_thread = queued; + if (!process_can_run(next_proc)) continue; + break; } - if (!next_proc && current_proc && current_proc != idle_proc && current_proc->state == RUNNING && process_can_run(current_proc)) next_proc = current_proc; - if (!next_proc || !process_can_run(next_proc)) { - next_proc = idle_proc; - print("Selected idle proc %llx",next_proc); + if (!next_proc && current_proc && current_proc != idle_proc && current_proc->state == RUNNING && process_can_run(current_proc)){ + next_proc = current_proc; + next_thread = (thread_t*)cpec; + } + if (!next_proc || !process_can_run(next_proc)){ + next_proc = idle_proc;//TODO: process can run is too restrictive, it could run, just need to find the right thread to run + next_thread = &idle_proc->main_thread; } if (!next_proc || !process_can_run(next_proc)) panic("no runnable process", 0); - //if (next_proc == idle_proc && prev != idle_proc) kprint("entering idle"); - - if (!next_proc->current_thread) next_proc->current_thread = &next_proc->main_thread; + + if (!next_thread || next_thread->pid != next_proc->id) next_thread = &next_proc->main_thread; next_proc->state = RUNNING; - next_proc->current_thread->state = RUNNING; + next_thread->state = RUNNING; current_proc = next_proc; - cpec = (uptr)next_proc->current_thread; + cpec = (uptr)next_thread; if (current_proc == idle_proc) timer_disable(); else { timer_enable(); @@ -232,6 +229,10 @@ process_t* get_current_proc(){ return current_proc; } +thread_t* get_current_thread(){ + return (thread_t*)cpec; +} + process_t* get_kernel_proc(){ return kernel_proc; } @@ -279,7 +280,6 @@ process_t* get_proc_by_pid(uint16_t pid){ } thread_t* get_thread_from_proc(process_t *proc, u16 tid){ - if (proc->current_thread->tid == tid) return proc->current_thread; thread_t *t = &proc->main_thread; do { if (t->tid == tid) return t; @@ -455,10 +455,8 @@ void reset_process(process_t *proc){ proc->mm.ttbr0 = 0; proc->mm.ttbr0_phys = 0; } - if (proc->exposed_fs.init){ - unload_module(&proc->exposed_fs); - } - proc->exposed_fs = (system_module){0}; + destroy_fs(proc->permissions.fs_id); + destroy_fs(proc->permissions.owned_fs_id); memset(proc->name, 0, sizeof(proc->name)); @@ -687,38 +685,8 @@ void wake_processes(){ irq_restore(irq); } -void unschedule_thread(process_t *proc, thread_t *t){ - if (!proc || !t || proc->id != t->pid) return; - thread_t *prev = &proc->main_thread; - thread_t *current = prev->next; - if (proc->current_thread == t){ - proc->thread_count--; - proc->current_thread = prev; - } - while (current) { - if (t == current){ - proc->thread_count--; - prev->next = current->next; - return; - } - prev = current; - current = current->next; - } -} - void schedule_thread(process_t *proc, thread_t *t){ - if (!proc || !t || proc->id != t->pid) return; - thread_t *current = &proc->main_thread; - while (current){ - if (!current->next){ - current->next = t; - proc->thread_count++; - kprintf("[SCHEDULER] scheduled thread %i for %i. pc %llx",t->tid,t->pid,t->pc); - t->state = READY; - return; - } - current = current->next; - } + enqueue_ready_thread(t); } thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point){ diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index d50505c8..e5f464da 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -49,6 +49,7 @@ bool load_process_module(process_t *p, system_module *m); process_t* get_current_proc(); process_t* get_kernel_proc(); process_t* get_idle_proc(); +thread_t* get_current_thread(); bool scheduler_in_idle(); process_t* get_proc_by_pid(uint16_t pid); uint16_t get_current_proc_pid(); @@ -64,7 +65,6 @@ process_t *get_all_processes(); thread_t* alloc_thread(); thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point); -void unschedule_thread(process_t *proc, thread_t *t); void schedule_thread(process_t *proc, thread_t *t); thread_t* get_thread_from_proc(process_t *proc, u16 tid); diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index b06ef239..fec80128 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -201,7 +201,6 @@ u64 syscall_halt_thread(process_t *ctx, thread_t *current_thread){ stop_current_process(current_thread->PROC_X0); else { current_thread->state = STOPPED; - unschedule_thread(ctx, current_thread); unmap_stack(ctx, current_thread->stack_info); switch_proc(YIELD);//TODO: proper cleanup } From d78cd1b19f8b153d9b6581baeac2041852895fd0 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 31 Jul 2026 00:00:00 +0000 Subject: [PATCH 49/65] [ENV] window info [THEME] refresh desktop --- kernel/filesystem/filesystem.c | 2 +- kernel/graph/tres.c | 9 ++++++++ kernel/graph/tres.h | 3 +++ kernel/kernel_processes/windows/dos.c | 22 ++++++++++++++---- kernel/process/environment/environment.c | 29 ++++++++++++++++++++++-- kernel/process/environment/environment.h | 4 +++- kernel/process/scheduler.c | 4 ++-- kernel/theme/theme.c | 3 +++ shared | 2 +- user/demo/default_process.c | 8 ++++++- 10 files changed, 74 insertions(+), 12 deletions(-) diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index 29b5ee11..b18e16fd 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -227,7 +227,7 @@ size_t simple_write(module_root *root, const char *path, const void *buf, size_t seek(&fd, fd.size, SEEK_ABSOLUTE); } size_t res = write_file(&fd, (char*)buf, size); - if (append){ + if (!append){ truncate(&fd, size); } close_file(&fd); diff --git a/kernel/graph/tres.c b/kernel/graph/tres.c index 5ec5f945..f5913f91 100644 --- a/kernel/graph/tres.c +++ b/kernel/graph/tres.c @@ -342,4 +342,13 @@ void set_window_focus(uint16_t win_id){ void unset_window_focus(){ focused_window = 0; +} + +void refresh_window_info(u16 wid, window_info_t *info){ + linked_list_node_t *node = linked_list_find(window_list, &wid, find_window); + if (!node || !node->data) return; + + window_frame *frame = node->data; + frame->info = *info; + dirty_windows = true; } \ No newline at end of file diff --git a/kernel/graph/tres.h b/kernel/graph/tres.h index 7bb126cd..e1c37088 100644 --- a/kernel/graph/tres.h +++ b/kernel/graph/tres.h @@ -15,6 +15,7 @@ typedef struct { uint32_t width, height; draw_ctx win_ctx; uint16_t pid; + window_info_t info; } window_frame; #define MENU_HEIGHT 50 @@ -33,6 +34,8 @@ void get_window_ctx(draw_ctx* out_ctx); void commit_frame(draw_ctx* frame_ctx, window_frame* frame, bool overwrite_focus); +void refresh_window_info(u16 wid, window_info_t *info); + u16 window_fallback_focus(u16 win_id, u16 skip_id); void set_window_focus(uint16_t win_id); void unset_window_focus(); diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index f19094f8..6f02633f 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -51,7 +51,15 @@ static void draw_solid_window(window_frame *frame, draw_ctx *ctx, int_point fixe .size = fixed_size, .background_color = saturate(system_theme.bg_color + 0x111111, focused ? 0 : -90), .foreground_color = COLOR_WHITE, - }), { + }), { + label(ctx, (text_ui_config){ + .slice = { frame->info.name, frame->info.name_length}, + .font_size = 3, + }, (common_ui_config){ + .point = RELATIVE(5, BORDER_SIZE+5), + .size = { parent.size.width-200, 30 }, + .foreground_color = system_theme.accent_color, + }); bool close_pressed = false; button(ctx, (rect_ui_config){}, (common_ui_config){ .point = RELATIVE(parent.size.width - (BORDER_SIZE * 2) - 40 - BORDER_SIZE,BORDER_SIZE), @@ -233,11 +241,17 @@ void check_shortcuts(){ } } } + +void refresh_desktop_colors(){ + setup_desktop_bg(); + draw_desktop(); + dirty_windows = true; +} + int window_system(){ disable_visual(); dos_ctx = gpu_get_ctx(); - setup_desktop_bg(); - draw_desktop(); + refresh_desktop_colors(); setup_shortcuts(); switch_cursor(cursor_crosshair); @@ -341,4 +355,4 @@ process_t* create_windowing_system(){ if (!win_system_proc) win_system_proc = create_kernel_process("dos", window_system, 0, 0); return win_system_proc; -} +} \ No newline at end of file diff --git a/kernel/process/environment/environment.c b/kernel/process/environment/environment.c index 8675010e..abacf2b9 100644 --- a/kernel/process/environment/environment.c +++ b/kernel/process/environment/environment.c @@ -1,8 +1,12 @@ #include "files/folderfs.h" #include "console/kio.h" +#include "graph/tres.h" +#include "process/scheduler.h" bool env_loaded = false; +#define DATA_WIN_SIGNATURE DATA_SIGNATURE("WININFO") + typedef struct { u16 procid; } env_data; @@ -48,6 +52,15 @@ FS_RESULT environment_open(u64 id, string_slice file_name, file *fd){ } return FS_RESULT_SUCCESS; } + if (slice_lit_match(file_name, "window", true)){ + print("Opening file %v",file_name); + fd->id = ((env_type_win & 0xFFFF) << 16) | id; + fd->data_type = DATA_WIN_SIGNATURE; + fd->size = sizeof(window_info_t); + if (!proc->environment.win_buf.buffer) + buffer_map_value(&proc->environment.win_buf, &proc->environment.win_info, sizeof(window_info_t), DATA_WIN_SIGNATURE); + return FS_RESULT_SUCCESS; + } return FS_RESULT_NOTFOUND; } @@ -63,6 +76,8 @@ buffer* environment_resolve_fd(file *fd){ return &proc->environment.data; case env_type_structure: return &proc->environment.structure; + case env_type_win: + return &proc->environment.win_buf; default: return 0; } return 0; @@ -76,6 +91,7 @@ bool environment_init(system_module *module){ static_entries += make_entry(":id/config", backing_virtual, entry_file, DATA_SIGNATURE("OUTFMT"), (buffer){}) != 0; static_entries += make_entry(":id/data", backing_virtual, entry_file, DATA_SIG_RAW, (buffer){}) != 0; static_entries += make_entry(":id/structure", backing_virtual, entry_file, DATA_SIG_DATA_STRUCT, (buffer){}) != 0; + static_entries += make_entry(":id/window", backing_virtual, entry_file, DATA_WIN_SIGNATURE, (buffer){}) != 0; return true; } @@ -85,13 +101,22 @@ void register_environment(u16 procid){ folderfs_create_folder(data); } +static inline size_t environment_write(file *fd, const char *buf, size_t size, file_offset offset){ + size_t s = buffer_write_lim(environment_resolve_fd(fd), (void*)buf, size); + u16 file_type = (fd->id >> 16) & 0xFFFF; + if (file_type == env_type_win && s == sizeof(window_info_t)){ + refresh_window_info(get_current_proc()->win_id,(window_info_t*)buf); + } + return s; +} + system_module environment_module = { .name = "environment", .mount = "environments", .version = VERSION_NUM(0, 1, 0, 0), .init = environment_init, - .read = folderfs_read , - .write = folderfs_write, + .read = folderfs_read, + .write = environment_write, .getstat = folderfs_stat, .readdir = folderfs_readdir, .open = folderfs_open, diff --git a/kernel/process/environment/environment.h b/kernel/process/environment/environment.h index 2003b100..f7c6a6bd 100644 --- a/kernel/process/environment/environment.h +++ b/kernel/process/environment/environment.h @@ -10,8 +10,10 @@ typedef struct { buffer data; buffer structure; buffer config_buf; + window_info_t win_info; + buffer win_buf; } environment_data; -typedef enum { env_type_none, env_type_config, env_type_data, env_type_structure } env_data_types; +typedef enum { env_type_none, env_type_config, env_type_data, env_type_structure, env_type_win } env_data_types; void register_environment(u16 procid); \ No newline at end of file diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 10b54536..dd170f48 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -74,7 +74,7 @@ bool process_has_runtime_state(process_t *proc){ return proc && (proc->main_thread.sp || proc->main_thread.pc || proc->main_thread.spsr || proc->main_thread.stack_info.size || proc->heap_phys || proc->mm.ttbr0 || proc->output || proc->alloc_map || proc->bundle || proc->code || proc->code_size || proc->va); } -bool process_can_run(process_t *proc){//TODO: thread, not proc based +bool process_can_run(process_t *proc){ if (!proc) return false; if (!process_is_known(proc) || proc->pending_reset) return false; if (proc->state == STOPPED || proc->suspended || !proc->main_thread.pc || !proc->main_thread.sp) return false; @@ -153,7 +153,7 @@ void switch_proc(ProcSwitchReason reason) { next_thread = (thread_t*)cpec; } if (!next_proc || !process_can_run(next_proc)){ - next_proc = idle_proc;//TODO: process can run is too restrictive, it could run, just need to find the right thread to run + next_proc = idle_proc; next_thread = &idle_proc->main_thread; } if (!next_proc || !process_can_run(next_proc)) panic("no runnable process", 0); diff --git a/kernel/theme/theme.c b/kernel/theme/theme.c index d00d184e..4cb7bc7f 100644 --- a/kernel/theme/theme.c +++ b/kernel/theme/theme.c @@ -160,8 +160,11 @@ bool load_theme(){ return true; } +extern void refresh_desktop_colors(); + size_t reload(file* fd, const char *buf, size_t size, file_offset offset){ load_theme(); + refresh_desktop_colors(); return 0; } diff --git a/shared b/shared index 4c6c12c5..cb92c758 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 4c6c12c5f152a9d037c733e1476e8a1d1503e104 +Subproject commit cb92c7584574491d847960883cd253b559aa1466 diff --git a/user/demo/default_process.c b/user/demo/default_process.c index ebf8b94c..ca841dc2 100644 --- a/user/demo/default_process.c +++ b/user/demo/default_process.c @@ -12,6 +12,7 @@ #include "utils/clipboard.h" #include "math/math.h" #include "draw/textdraw.h" +#include "environment/env_types.h" draw_ctx ctx = {}; @@ -207,6 +208,12 @@ int main(int argc, char* argv[]){ handle_signal(SIG_QUIT, on_quit); // send_signal(SIG_QUIT, 7);//TODO: get own procid? + window_info_t info = { + .name = "Demo program", + .name_length = 12 + }; + env_set_window_info(&info); + request_draw_ctx(&ctx); gpu_point cursor = {}; @@ -229,7 +236,6 @@ int main(int argc, char* argv[]){ string f = string_format("[%i]: %s\n",i+1, demos[i].name); range.size = f.length; fb_continuous_draw_text(&ctx, draw_text_render, &cursor, slice_from_string(f), &range, rect, &size, (gpu_point){}, text_fmt, (text_format_arr){ }); - print("%i,%i - %i,%i",range.start,range.size,cursor.x,cursor.y); string_free(f); } From 77e4d7ef5a265274d5e7cd2f58e384769a75566a Mon Sep 17 00:00:00 2001 From: di Date: Fri, 31 Jul 2026 00:00:00 +0000 Subject: [PATCH 50/65] [FS_MOD,WIP] basic menu fs test in filebrowser, crashes on subdirs Signed-off-by: di --- kernel/process/jobs/job_manager.h | 5 +---- kernel/process/scheduler.c | 6 ++++-- kernel/process/scheduler.h | 2 +- kernel/process/syscall.c | 3 ++- shared | 2 +- user/filebrowser/main.c | 35 ++++++++++++++++++++++++++----- user/terminal/main.c | 2 +- 7 files changed, 40 insertions(+), 15 deletions(-) diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index fe572812..34def629 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -5,9 +5,6 @@ //TODO: We can probably optimize current proc fs more, but right now it blocks the entire process so we can't allow this case #define job_make(job_type,mod,action)\ -if (get_current_proc()->id == mod->owner){\ - return false;\ -}\ process_t *owner_proc = get_proc_by_pid(mod->owner);\ if (!is_privileged(owner_proc)){\ job_application_t app = (job_application_t){\ @@ -77,7 +74,7 @@ static inline void job_serialize_off(job_application_t *application, int arg_num job_buffer buf = { .worker_ptr = {.ptr = (uptr)offset, .size = sizeof(file_offset *) }, .orig_ptr = {.ptr = (uptr)offset, .size = sizeof(file_offset *) }, - .sync = copy_on_end, + .sync = copy_on_start | copy_on_end, .arg_num = arg_num, .explicit_size = false, }; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index dd170f48..c51a8e6e 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -708,7 +708,7 @@ thread_t* new_thread(process_t *proc, thread_t *addr, u64 spsr, uptr entry_point return addr; } -bool load_process_module(process_t *p, system_module *m){//TODO: this doesn't belong here +bool load_process_module(process_t *p, system_module *m, bool global){//TODO: this doesn't belong here if (!p->permissions.owned_fs_id) p->permissions.owned_fs_id = register_fs_id(); module_root *root = get_fs_for_id(p->permissions.fs_id); system_module *mod = zalloc(sizeof(system_module)); @@ -716,6 +716,8 @@ bool load_process_module(process_t *p, system_module *m){//TODO: this doesn't be mod->name = string_from_literal(m->name).data; mod->mount = string_from_literal(m->mount).data; mod->owner = p->id; - load_module_to(root, mod); + bool ret = load_module_to(root, mod); + if (!ret) return false; + if (!global) return true; return load_module(mod); } diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index e5f464da..32b56958 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -44,7 +44,7 @@ void name_process(process_t *proc, const char *name); void sleep_thread(uint64_t msec); void wake_processes(); -bool load_process_module(process_t *p, system_module *m); +bool load_process_module(process_t *p, system_module *m, bool global); process_t* get_current_proc(); process_t* get_kernel_proc(); diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index fec80128..9016775e 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -484,7 +484,8 @@ u64 syscall_signal_handler(process_t* ctx, thread_t *current_thread){ uint64_t syscall_load_fsmod(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(system_module,mod,PROC_X0, false); - return load_process_module(ctx,mod); + bool global = current_thread->PROC_X1; + return load_process_module(ctx,mod,global); } uint64_t syscall_unload_fsmod(process_t *ctx, thread_t *current_thread){ diff --git a/shared b/shared index cb92c758..7e1c7a35 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit cb92c7584574491d847960883cd253b559aa1466 +Subproject commit 7e1c7a359fa1e022d7b058871cc06ce697e2b6a6 diff --git a/user/filebrowser/main.c b/user/filebrowser/main.c index 2d57698a..55075401 100644 --- a/user/filebrowser/main.c +++ b/user/filebrowser/main.c @@ -3,14 +3,39 @@ #include "input_keycodes.h" #include "data/struct/stack.h" #include "header_utils/filebrowser.h" +#include "files/vfs.h" -int main(){ - request_draw_ctx(&filebrowser_ctx); +size_t test_fn(file *fd, const char *c, size_t s, file_offset off){ + print("Test button pressed"); + return 0; +} - file descriptor = {}; - openf("/termhistory", &descriptor); +void menu_init(){ + make_entry("File", backing_virtual, entry_directory, 0, (buffer){}); + make_entry("File" "/" "Hello", backing_virtual, entry_file, 0, (buffer){}); + make_entry("Edit", backing_virtual, entry_directory, 0, (buffer){}); + make_entry("Edit/World", backing_virtual, entry_directory, 0, (buffer){}); + // make_complex_entry("File/Test", backing_transform, entry_file, 0, (file_actions){.write = test_fn}, (string){}); +} + +system_module menu_mod = { + .name = "demo menu", + .mount = "menu", + //TODO: can init be brought back now? + .version = VERSION_NUM(0, 1, 0, 0), + .open = vfs_open, + .read = vfs_read, + .write = vfs_write, + .getstat = vfs_stat, + .readdir = vfs_readdir, +}; - print("Descriptor id %i of type %s and size %i",descriptor.id,&descriptor.data_type,descriptor.size); +int main(){ +#if false + menu_init(); + load_fsmodule(&menu_mod, true); +#endif + request_draw_ctx(&filebrowser_ctx); files = stack_create(sizeof(file_data),32); directories = stack_create(sizeof(string),16); diff --git a/user/terminal/main.c b/user/terminal/main.c index 8accc21f..bb4b45d2 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -321,7 +321,7 @@ int main(){ screen_printer_init(dummy_draw_ctx(ctx.width, ctx.height-INPUT_HEIGHT)); stackfs_init(); - load_fsmodule(&termhistory_mod); + load_fsmodule(&termhistory_mod, true); u32 color_buf[2] = {}; sreadf("/theme", &color_buf, sizeof(uint64_t)); From a55a46a9739a2dbfe6b95b10d6673512df124329 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 31 Jul 2026 00:00:00 +0000 Subject: [PATCH 51/65] [FS] usfs read/write Signed-off-by: di --- kernel/filesystem/filesystem.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index b18e16fd..7c8c39d8 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -128,7 +128,10 @@ size_t read_file(file *descriptor, char* buf, size_t size){ }; size_t amount_read = 0; if (local.mod->owner != get_kernel_proc()->id){ - kprintf("cba rn"); + job_make(job_readdir, local.mod, { + job_serialize_fd(&app, 0, &gfd, copy_on_start); + job_serialize_buf(&app, 1, true, (void*)buf, size, copy_on_end); + }); return amount_read; } else { amount_read = local.mod->read(&gfd, buf, size, start_cursor); @@ -188,7 +191,10 @@ size_t write_file(file *descriptor, const char* buf, size_t size){ }; size_t amount_written = 0; if (local.mod->owner != get_kernel_proc()->id){ - kprintf("cba rn"); + job_make(job_readdir, local.mod, { + job_serialize_fd(&app, 0, &gfd, copy_on_start); + job_serialize_buf(&app, 1, true, (void*)buf, size, copy_on_start); + }); return amount_written; } else { amount_written = local.mod->write(&gfd, buf, size, 0); From 4e25795c6f10540ff83ce7eea23ecb5996817bf7 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 31 Jul 2026 00:00:00 +0000 Subject: [PATCH 52/65] [JOB] zero memory when creating it Signed-off-by: di --- kernel/process/jobs/job_manager.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index b1fd5bdd..b4c6316b 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -57,6 +57,7 @@ bool prepare_thread(job_state_t *job, system_module *mod, job_application_t appl mmu_map_4kb(proc->mm.ttbr0, buffers + (i * PAGE_SIZE), pbuffers + (i * PAGE_SIZE), MAIR_IDX_NORMAL, MEM_RW, MEM_PRIV_USER); register_proc_memory(PHYS_TO_VIRT(pbuffers + (i * PAGE_SIZE)), pbuffers + (i * PAGE_SIZE), MEM_RW, MEM_PRIV_KERNEL); } + memset((void*)PHYS_TO_VIRT(pbuffers), 0, total_size); print("[JOB debug] buffers will go to %llx - %llx",buffers,pbuffers); uptr next_addr_pa = PHYS_TO_VIRT(pbuffers); uptr next_addr_va = buffers; From 1abd00fe7e0af1225734712a9a94e36a196a552d Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 53/65] [TERMINAL] made usfs fully vanilla [JOB] fixed job descriptor for read/write [FILEBROWSER] restored complex entry test Signed-off-by: di --- kernel/filesystem/filesystem.c | 4 ++-- shared | 2 +- user/filebrowser/main.c | 4 +--- user/terminal/main.c | 10 +--------- 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index 7c8c39d8..02d7d49b 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -128,7 +128,7 @@ size_t read_file(file *descriptor, char* buf, size_t size){ }; size_t amount_read = 0; if (local.mod->owner != get_kernel_proc()->id){ - job_make(job_readdir, local.mod, { + job_make(job_read, local.mod, { job_serialize_fd(&app, 0, &gfd, copy_on_start); job_serialize_buf(&app, 1, true, (void*)buf, size, copy_on_end); }); @@ -191,7 +191,7 @@ size_t write_file(file *descriptor, const char* buf, size_t size){ }; size_t amount_written = 0; if (local.mod->owner != get_kernel_proc()->id){ - job_make(job_readdir, local.mod, { + job_make(job_write, local.mod, { job_serialize_fd(&app, 0, &gfd, copy_on_start); job_serialize_buf(&app, 1, true, (void*)buf, size, copy_on_start); }); diff --git a/shared b/shared index 7e1c7a35..23b0f4df 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 7e1c7a359fa1e022d7b058871cc06ce697e2b6a6 +Subproject commit 23b0f4dfb00e7ac83aaeae7e1b20af4dcf8bc862 diff --git a/user/filebrowser/main.c b/user/filebrowser/main.c index 55075401..39a537fc 100644 --- a/user/filebrowser/main.c +++ b/user/filebrowser/main.c @@ -15,7 +15,7 @@ void menu_init(){ make_entry("File" "/" "Hello", backing_virtual, entry_file, 0, (buffer){}); make_entry("Edit", backing_virtual, entry_directory, 0, (buffer){}); make_entry("Edit/World", backing_virtual, entry_directory, 0, (buffer){}); - // make_complex_entry("File/Test", backing_transform, entry_file, 0, (file_actions){.write = test_fn}, (string){}); + make_complex_entry("File/Test", backing_transform, entry_file, 0, (file_actions){.write = test_fn}, (string){}); } system_module menu_mod = { @@ -31,10 +31,8 @@ system_module menu_mod = { }; int main(){ -#if false menu_init(); load_fsmodule(&menu_mod, true); -#endif request_draw_ctx(&filebrowser_ctx); files = stack_create(sizeof(file_data),32); diff --git a/user/terminal/main.c b/user/terminal/main.c index bb4b45d2..4c24a9be 100644 --- a/user/terminal/main.c +++ b/user/terminal/main.c @@ -296,19 +296,11 @@ size_t custom_readdir(const char *path, void *buf, size_t size, file_offset *off return dir_buf_size(&helper); } -FS_RESULT custom_open(const char *path, file *fd){ - fd->id = 1; - print("Sending id %i",fd->id); - fd->size = 100; - fd->data_type = DATA_SIGNATURE("ASYNC"); - return FS_RESULT_SUCCESS; -} - system_module termhistory_mod = { .name = "terminal history", .mount = "termhistory", .version = VERSION_NUM(0, 1, 0, 0), - .open = custom_open, + .open = stackfs_open, .read = stackfs_read, .write = stackfs_write, .readdir = custom_readdir, From 8b73ccae6520025ec3ec2f7f081454d2033752dd Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 54/65] [PROJ] warning fixes Signed-off-by: di --- libs/LibMakefile | 3 --- libs/regex | 2 +- shared | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/libs/LibMakefile b/libs/LibMakefile index 938b0ad5..4e6a584c 100644 --- a/libs/LibMakefile +++ b/libs/LibMakefile @@ -21,11 +21,8 @@ all: prepare $(TARGET) prepare: mkdir -p $(BUILD_DIR) - @echo "C Sources $(C_SRC)" $(TARGET): $(OBJ) - @echo "Finishing build $(ARCH)" - @echo $(addprefix $(BUILD_DIR)/,$(notdir $(OBJ))) $(VAR) rcs $@ $(OBJ) $(BUILD_DIR)/%.o: %.c diff --git a/libs/regex b/libs/regex index d12ce58c..85bc5e9f 160000 --- a/libs/regex +++ b/libs/regex @@ -1 +1 @@ -Subproject commit d12ce58c54af70f84ac30637077e4dea3b6febae +Subproject commit 85bc5e9ffbc390e7b41aadc98951a017cfe26861 diff --git a/shared b/shared index 23b0f4df..8c838444 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 23b0f4dfb00e7ac83aaeae7e1b20af4dcf8bc862 +Subproject commit 8c838444499309fcdcde2fca0fda714fa2c15074 From ba19ef275e538410cf4a4951b68ce92181c4edcb Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 55/65] [JOB] open fix and read/write/trunc operations Signed-off-by: di --- kernel/filesystem/filesystem.c | 2 +- kernel/process/jobs/job_manager.c | 9 ++++++++- shared | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index 02d7d49b..934361b2 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -57,7 +57,7 @@ FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor FS_RESULT result = FS_RESULT_DRIVER_ERROR; if (mod->owner != get_kernel_proc()->id){ job_make(job_open, mod, { - job_serialize_str(&app, 0, path); + job_serialize_str(&app, 0, search_path); job_serialize_fd(&app, 1, descriptor, copy_on_end); }); return 0; diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index b4c6316b..dd9362bf 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -43,6 +43,9 @@ bool prepare_thread(job_state_t *job, system_module *mod, job_application_t appl case job_readdir: entry = (uptr)mod->readdir; break; case job_open: entry = (uptr)mod->open; break; case job_close: entry = (uptr)mod->close; break; + case job_read: entry = (uptr)mod->read; break; + case job_write: entry = (uptr)mod->write; break; + case job_trunc: entry = (uptr)mod->truncate; break; default: return false; } if (!entry) return false; @@ -81,6 +84,7 @@ job_id_t create_new_job(job_application_t application, system_module *mod){ process_t *requesting_proc = get_proc_by_pid(application.requesting_pid); if (!requesting_proc){ print("[JOB error] Unknown requesting proc %i",application.requesting_pid); + return (job_id_t){}; } job_state_t *job = job_alloc(); job->type = application.type; @@ -89,7 +93,10 @@ job_id_t create_new_job(job_application_t application, system_module *mod){ job->requester = requester; process_t *fs_owner = get_proc_by_pid(application.worker_pid); thread_t *new_t = alloc_thread(); - if (!prepare_thread(job, mod, application, fs_owner, new_t)) return false; + if (!prepare_thread(job, mod, application, fs_owner, new_t)){ + print("[JOB error] failed to prepare thread for job %i",job->id); + return false; + } print("[JOB debug] Sync between %i - %i will happen with job %i of type %i using thread %i",requester->pid,application.worker_pid,job->id,application.type,new_t->tid); new_t->job_id = job->id; job->worker = new_t; diff --git a/shared b/shared index 8c838444..7449400a 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 8c838444499309fcdcde2fca0fda714fa2c15074 +Subproject commit 7449400aae7e5d49d45497fa87f2ac46a3c2e44b From 221756edf3dfbc287f2c27ee5567bf58d8e0f401 Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 56/65] [MENU, WIP] get menu from application, disabled due to job system not working in kernel space Signed-off-by: di --- kernel/input/input_dispatch.c | 8 +++++-- kernel/kernel_processes/windows/menu.c | 30 ++++++++++++++++++++++++ kernel/kernel_processes/windows/menu.h | 3 ++- kernel/process/environment/environment.c | 15 ++++++++++++ kernel/process/environment/environment.h | 2 +- kernel/process/jobs/job_manager.c | 6 ++--- user/filebrowser/main.c | 14 +++++++++-- 7 files changed, 69 insertions(+), 9 deletions(-) diff --git a/kernel/input/input_dispatch.c b/kernel/input/input_dispatch.c index 194c4e8f..a851d305 100644 --- a/kernel/input/input_dispatch.c +++ b/kernel/input/input_dispatch.c @@ -4,6 +4,7 @@ #include "math/math.h" #include "graph/graphics.h" #include "graph/tres.h" +#include "kernel_processes/windows/menu.h" process_t* focused_proc; @@ -179,11 +180,14 @@ void sys_focus_current(){ void sys_set_focus(int pid){ process_t *target = get_proc_by_pid(pid); if (!target || target->state == STOPPED || !target->id || !target->main_thread.pc || !target->main_thread.sp || (!is_privileged(target) && !target->mm.ttbr0)) return; + if (focused_proc && focused_proc->id == pid) return; if (focused_proc) focused_proc->focused = false; focused_proc = target; focused_proc->focused = true; - kprintf("New focus %i",pid); - if (system_config.use_windows) set_window_focus(focused_proc->win_id); + if (system_config.use_windows){ + set_window_focus(focused_proc->win_id); + refresh_menu(); + } } void sys_unset_focus(bool close){ diff --git a/kernel/kernel_processes/windows/menu.c b/kernel/kernel_processes/windows/menu.c index 5f0f9daf..2e406121 100644 --- a/kernel/kernel_processes/windows/menu.c +++ b/kernel/kernel_processes/windows/menu.c @@ -6,6 +6,8 @@ #include "theme/theme.h" #include "syscalls/syscalls.h" #include "input/input_dispatch.h" +#include "filesystem/modules/fs_isolation.h" +#include "filesystem/filesystem.h" #define draw_eye(x_off, blink, eyelid) fb_fill_rect(ctx, rect.point.x + eye_margin + x_off, rect.point.y + (rect.size.height * 0.1), eye_size.width, eye_size.height, (blink) ? eyelid : 0xFFcccccc);\ fb_fill_rect(ctx, rect.point.x + eye_margin + p.x + x_off, rect.point.y + (rect.size.height * 0.1) + p.y, eye_size.width-pupil_distance.width, eye_size.height-pupil_distance.height, (blink) ? eyelid : 0xFF333333); @@ -33,7 +35,35 @@ void test_widget(draw_ctx *ctx, gpu_rect rect, color bg){ } +bool menu_dirty = true; + +void refresh_menu(){ +#if false + menu_dirty = true; +#endif +} + +void load_menu(){ + process_t *menu_proc = get_proc_by_pid(sys_get_focused_pid()); + if (!menu_proc){ print("[MENU debug] no focused process"); return; } + const char *path = "/menu"; + module_root *localfs = get_fs_for_id(menu_proc->permissions.fs_id); + + if (!localfs) return; + + void *buf = zalloc(0x1000); + u64 off = 0; + size_t s = list_directory_contents(localfs, path, buf, 0x1000, &off); + print("Size of read %x",s); + + print("There are %i entries",*(u32*)buf); +} + void draw_menu(){ + if (menu_dirty){ + load_menu(); + menu_dirty = false; + } draw_ctx *screen_ctx = gpu_get_ctx(); fb_fill_rect(screen_ctx, 0, 0, screen_ctx->width, MENU_HEIGHT, system_theme.bg_color+0x111111); fb_fill_rect(screen_ctx, 0, MENU_HEIGHT-BORDER_SIZE, screen_ctx->width, BORDER_SIZE, 0x44000000); diff --git a/kernel/kernel_processes/windows/menu.h b/kernel/kernel_processes/windows/menu.h index 41683bbd..a37d4d19 100644 --- a/kernel/kernel_processes/windows/menu.h +++ b/kernel/kernel_processes/windows/menu.h @@ -1,3 +1,4 @@ #pragma once -void draw_menu(); \ No newline at end of file +void draw_menu(); +void refresh_menu(); \ No newline at end of file diff --git a/kernel/process/environment/environment.c b/kernel/process/environment/environment.c index abacf2b9..ec2a1d12 100644 --- a/kernel/process/environment/environment.c +++ b/kernel/process/environment/environment.c @@ -2,6 +2,7 @@ #include "console/kio.h" #include "graph/tres.h" #include "process/scheduler.h" +#include "kernel_processes/windows/menu.h" bool env_loaded = false; @@ -61,6 +62,12 @@ FS_RESULT environment_open(u64 id, string_slice file_name, file *fd){ buffer_map_value(&proc->environment.win_buf, &proc->environment.win_info, sizeof(window_info_t), DATA_WIN_SIGNATURE); return FS_RESULT_SUCCESS; } + if (slice_lit_match(file_name, "menu", true)){ + fd->id = ((env_type_menu & 0xFFFF) << 16) | id; + fd->data_type = 0; + fd->size = 0; + return FS_RESULT_SUCCESS; + } return FS_RESULT_NOTFOUND; } @@ -78,6 +85,8 @@ buffer* environment_resolve_fd(file *fd){ return &proc->environment.structure; case env_type_win: return &proc->environment.win_buf; + case env_type_menu: + return 0; default: return 0; } return 0; @@ -92,6 +101,7 @@ bool environment_init(system_module *module){ static_entries += make_entry(":id/data", backing_virtual, entry_file, DATA_SIG_RAW, (buffer){}) != 0; static_entries += make_entry(":id/structure", backing_virtual, entry_file, DATA_SIG_DATA_STRUCT, (buffer){}) != 0; static_entries += make_entry(":id/window", backing_virtual, entry_file, DATA_WIN_SIGNATURE, (buffer){}) != 0; + static_entries += make_entry(":id/menu", backing_virtual, entry_file, 0, (buffer){}) != 0; return true; } @@ -106,6 +116,11 @@ static inline size_t environment_write(file *fd, const char *buf, size_t size, f u16 file_type = (fd->id >> 16) & 0xFFFF; if (file_type == env_type_win && s == sizeof(window_info_t)){ refresh_window_info(get_current_proc()->win_id,(window_info_t*)buf); + } + if (file_type == env_type_menu){ + process_t *menu_proc = get_current_proc(); + if (!menu_proc->focused) return 0; + refresh_menu(); } return s; } diff --git a/kernel/process/environment/environment.h b/kernel/process/environment/environment.h index f7c6a6bd..bc20fe2c 100644 --- a/kernel/process/environment/environment.h +++ b/kernel/process/environment/environment.h @@ -14,6 +14,6 @@ typedef struct { buffer win_buf; } environment_data; -typedef enum { env_type_none, env_type_config, env_type_data, env_type_structure, env_type_win } env_data_types; +typedef enum { env_type_none, env_type_config, env_type_data, env_type_structure, env_type_win, env_type_menu } env_data_types; void register_environment(u16 procid); \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index dd9362bf..f87cec3f 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -68,7 +68,7 @@ bool prepare_thread(job_state_t *job, system_module *mod, job_application_t appl for (size_t i = 0; i < application.buffer_count; i++){ job_buffer buf = application.buffers[i]; job->buffers[job->buffer_count++] = buf; - if (buf.sync & copy_on_start) + if (buf.sync & copy_on_start && buf.worker_ptr.ptr) memcpy((void*)next_addr_pa, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); t->regs[buf.arg_num] = next_addr_va; job->buffers[i].worker_ptr.ptr = next_addr_va; @@ -142,10 +142,10 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ st->requester->PROC_X0 = ret; for (size_t i = 0; i < st->buffer_count; i++){ job_buffer buf = st->buffers[i]; - if (buf.sync & copy_on_end){ + if (buf.sync & copy_on_end && buf.worker_ptr.ptr){ print("[JOB debug] Copy buffer %x into %x",buf.worker_ptr.ptr,buf.orig_ptr.ptr); void* addr = quick_translate(st->requester, proc, buf.orig_ptr.ptr); - if (!addr) return; + if (!addr) continue; memcpy(addr, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); file *fd = addr; if (buf.fd){ diff --git a/user/filebrowser/main.c b/user/filebrowser/main.c index 39a537fc..51b1b96f 100644 --- a/user/filebrowser/main.c +++ b/user/filebrowser/main.c @@ -18,6 +18,13 @@ void menu_init(){ make_complex_entry("File/Test", backing_transform, entry_file, 0, (file_actions){.write = test_fn}, (string){}); } +size_t custom_readdir(const char *path, void *buf, size_t size, file_offset *offset){ + print(">>>>>>>Hello"); + size_t ret = vfs_readdir(path, buf, size, offset); + print(">>> %x",ret); + return ret; +} + system_module menu_mod = { .name = "demo menu", .mount = "menu", @@ -27,12 +34,15 @@ system_module menu_mod = { .read = vfs_read, .write = vfs_write, .getstat = vfs_stat, - .readdir = vfs_readdir, + .readdir = custom_readdir, }; int main(){ menu_init(); - load_fsmodule(&menu_mod, true); + load_fsmodule(&menu_mod, false); + + swritef("/environment/menu", 0, 0, false); + request_draw_ctx(&filebrowser_ctx); files = stack_create(sizeof(file_data),32); From 187fb900bcccb34a5ec7d30c0ada6636bf7323d7 Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 57/65] [FS] reserve mount points Signed-off-by: di --- kernel/filesystem/modules/fs_isolation.c | 31 ++++++++++---------- kernel/filesystem/modules/fs_isolation.h | 9 ++++-- kernel/filesystem/modules/module_loader.c | 35 ++++++++++++++++------- kernel/filesystem/modules/module_loader.h | 1 + kernel/kernel.c | 2 ++ kernel/process/kernel_syscall_impl.c | 2 +- kernel/process/syscall.c | 2 +- 7 files changed, 51 insertions(+), 31 deletions(-) diff --git a/kernel/filesystem/modules/fs_isolation.c b/kernel/filesystem/modules/fs_isolation.c index 03dd1dbc..d0e95a4d 100644 --- a/kernel/filesystem/modules/fs_isolation.c +++ b/kernel/filesystem/modules/fs_isolation.c @@ -8,42 +8,43 @@ chunk_array_t *fs_permissions; u64 register_fs_id(){ if (!fs_permissions) fs_permissions = chunk_array_create(sizeof(uptr), 256); - hash_map_t *map = hash_map_create(64); - return chunk_array_push(fs_permissions, &map); + module_root *map = zalloc(sizeof(module_root)); + map->map = hash_map_create(64); + return chunk_array_push(fs_permissions, map); } -hash_map_t* get_fs_for_id(u64 id){ +module_root* get_fs_for_id(u64 id){ if (!fs_permissions) return 0; - return *(hash_map_t**)chunk_array_get(fs_permissions, id); + return (module_root*)chunk_array_get(fs_permissions, id); } -hash_map_t* kernel_modules; +module_root kernel_modules = {}; -hash_map_t* kernel_fs(){ - return kernel_modules; +module_root* kernel_fs(){ + return &kernel_modules; } bool load_module(system_module *module){ - if (!kernel_modules) kernel_modules = hash_map_create(64); - return load_module_to(kernel_modules, module); + if (!kernel_modules.map) kernel_modules.map = hash_map_create(64); + return load_module_to(&kernel_modules, module); } bool unload_module(system_module *module){ - return unload_module_from(kernel_modules, module); + return unload_module_from(&kernel_modules, module); } system_module* get_module(const char **full_path){ - return get_module_from(kernel_modules, full_path); + return get_module_from(&kernel_modules, full_path); } size_t list_root(void* buf, size_t size, uint64_t *offset){ fs_dir_list_helper helper = create_dir_list_helper(buf, size); - return list_root_from(kernel_modules, &helper, offset); + return list_root_from(&kernel_modules, &helper, offset); } string resolve_isolated_path(const char *path, u64 id, module_root *resolved, bool allow_kfs){ if (!path || !resolved || !id) return (string){}; - hash_map_t *localfs = get_fs_for_id(id); + module_root *localfs = get_fs_for_id(id); const char *localpath = path; system_module *localmod = get_module_from(localfs, &localpath); if (!localmod){ @@ -53,7 +54,7 @@ string resolve_isolated_path(const char *path, u64 id, module_root *resolved, bo if (!rootmod){ return (string){}; } - memcpy(resolved,kernel_modules,sizeof(module_root)); + memcpy(resolved,&kernel_modules,sizeof(module_root)); return string_from_literal(path); } if (localmod->alias_info.alias_path.length){ @@ -61,7 +62,7 @@ string resolve_isolated_path(const char *path, u64 id, module_root *resolved, bo const char *rootpath = s.data; system_module *rootmod = get_module(&rootpath); if (!rootmod) return (string){}; - memcpy(resolved,kernel_modules,sizeof(module_root)); + memcpy(resolved,&kernel_modules,sizeof(module_root)); return s; } memcpy(resolved,localfs,sizeof(module_root)); diff --git a/kernel/filesystem/modules/fs_isolation.h b/kernel/filesystem/modules/fs_isolation.h index 3e4a29cb..e4e754d1 100644 --- a/kernel/filesystem/modules/fs_isolation.h +++ b/kernel/filesystem/modules/fs_isolation.h @@ -3,11 +3,14 @@ #include "data/struct/linked_list.h" #include "files/system_module.h" -typedef hash_map_t module_root; +typedef struct { + hash_map_t *map; + hash_map_t *reserved; +} module_root; u64 register_fs_id(); -hash_map_t* get_fs_for_id(u64 id); -hash_map_t* kernel_fs(); +module_root* get_fs_for_id(u64 id); +module_root* kernel_fs(); #ifdef __cplusplus extern "C" { diff --git a/kernel/filesystem/modules/module_loader.c b/kernel/filesystem/modules/module_loader.c index 6e77bf50..11215acb 100644 --- a/kernel/filesystem/modules/module_loader.c +++ b/kernel/filesystem/modules/module_loader.c @@ -25,13 +25,21 @@ system_module root_module = { .readdir = 0, }; -bool load_module_to(hash_map_t* modules, system_module *module){ +bool reserve_mount_point(module_root* modules, char* mount_point){ + if (!modules->reserved) modules->reserved = hash_map_create(64); + if (hash_map_get_dictionary(modules->reserved, mount_point)){ print("[MODULE] %s already reserved",mount_point); return false; } + hash_map_put_dictionary(modules->reserved, mount_point, (void*)((u64)get_kernel_proc()->id)); + print("[MODULE] Reserved %s",mount_point); + return false; +} + +bool load_module_to(module_root* modules, system_module *module){ if (module->owner == get_kernel_proc()->id && !module->init){ - if (strcmp(module->mount,"/console")) kprintf("[MODULE] module not initialized due to missing initializer");//TODO: can we make printf silently fail so logging becomes easier? + if (strcmp(module->mount,"/console")) kprintf("[MODULE error] module not initialized due to missing initializer");//TODO: can we make printf silently fail so logging becomes easier? return false; } if (!module->version){ - string format = string_format("Version number cannot be null for module /%s",module->mount); + string format = string_format("[MODULE error] Version number cannot be null for module /%s",module->mount); if (strcmp(module->mount,"/console")) { #ifdef MODULE_STRICT if (module->owner != get_kernel_proc()->id){ @@ -48,14 +56,19 @@ bool load_module_to(hash_map_t* modules, system_module *module){ } if (!module->owner) module->owner = get_kernel_proc()->id; if (module->owner == get_kernel_proc()->id && !module->init(module)){ - if (strcmp(module->mount,"/console")) kprintf("[MODULE] failed to load module %s. Init failed",module->name); + if (strcmp(module->mount,"/console")) kprintf("[MODULE error] failed to load module %s. Init failed",module->name); + return false; + } + if (!modules->map) modules->map = hash_map_create(64); + if (modules->reserved && hash_map_get_dictionary(modules->reserved, module->mount)){ + kprintf("[MODULE error] mount point %s is reserved",module->mount); return false; } - hash_map_put_dictionary(modules, module->mount, PHYS_TO_VIRT_P(module)); + hash_map_put_dictionary(modules->map, module->mount, PHYS_TO_VIRT_P(module)); return true; } -bool unload_module_from(hash_map_t* modules, system_module *module){ +bool unload_module_from(module_root* modules, system_module *module){ if (!modules) return false; if (module->owner == get_kernel_proc()->id){ if (!module->init) return false; @@ -64,11 +77,11 @@ bool unload_module_from(hash_map_t* modules, system_module *module){ } else module->fini(); } - hash_map_remove(modules, module->mount, strlen(module->mount), 0); + hash_map_remove(modules->map, module->mount, strlen(module->mount), 0); return false; } -system_module* get_module_from(hash_map_t* modules, const char **full_path){ +system_module* get_module_from(module_root* modules, const char **full_path){ if (!modules) return 0; if (!full_path || !*full_path) return 0; const char *path = *full_path; @@ -90,7 +103,7 @@ system_module* get_module_from(hash_map_t* modules, const char **full_path){ if (!mod_name.length){ return &root_module; } - return hash_map_get(modules, mod_name.data, mod_name.length); + return hash_map_get(modules->map, mod_name.data, mod_name.length); } static u64 index = 0, count = 0; @@ -110,13 +123,13 @@ void iterate_root(void* key, u64 keylen, void* value){ } } -size_t list_root_from(hash_map_t* modules, fs_dir_list_helper *helper, uint64_t *offset){ +size_t list_root_from(module_root* modules, fs_dir_list_helper *helper, uint64_t *offset){ dir_helper = helper; index = offset ? *offset : 0; count = 0; - hash_map_for_each(modules, iterate_root); + hash_map_for_each(modules->map, iterate_root); return dir_buf_size(helper); } diff --git a/kernel/filesystem/modules/module_loader.h b/kernel/filesystem/modules/module_loader.h index f53a2ea0..82eadcb2 100644 --- a/kernel/filesystem/modules/module_loader.h +++ b/kernel/filesystem/modules/module_loader.h @@ -5,6 +5,7 @@ #include "fs_isolation.h" #include "files/dir_list.h" +bool reserve_mount_point(module_root* modules, char* mount_point); bool load_module_to(module_root* modules, system_module *module); bool unload_module_from(module_root* modules, system_module *module); system_module* get_module_from(module_root* modules, const char **full_path); diff --git a/kernel/kernel.c b/kernel/kernel.c index 8877b9af..7aaa7ab1 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -91,6 +91,8 @@ void kernel_main(uint64_t board_type, uint64_t dtb_pa) { } kprint("Kernel initialization finished"); + + reserve_mount_point(kernel_fs(), "menu"); kprint("Starting processes"); diff --git a/kernel/process/kernel_syscall_impl.c b/kernel/process/kernel_syscall_impl.c index 5f7324ea..f9c35be9 100644 --- a/kernel/process/kernel_syscall_impl.c +++ b/kernel/process/kernel_syscall_impl.c @@ -171,7 +171,7 @@ size_t dir_list(const char *path, void *buf, size_t size, u64 *offset){ if (!s.data || !s.length || strncmp(s.data,"/",s.length) == 0){ size_t ret = 0; fs_dir_list_helper helper = create_dir_list_helper(buf, size); - if (rootfs.buckets != kernel_fs()->buckets){ + if (rootfs.map->buckets != kernel_fs()->map->buckets){ ret += list_root_from(&rootfs, &helper, offset); } if (ret >= size) return ret; diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 9016775e..7ccbaa42 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -429,7 +429,7 @@ u64 syscall_dir_list(process_t *ctx, thread_t *current_thread){ if (!s.data || !s.length || strncmp(s.data,"/",s.length) == 0){ size_t ret = 0; fs_dir_list_helper helper = create_dir_list_helper(buf, size); - if (rootfs.buckets != kernel_fs()->buckets){ + if (rootfs.map->buckets != kernel_fs()->map->buckets){ ret += list_root_from(&rootfs, &helper, offset); } if (ret >= size) return ret; From c372d9a68217fe5b0c237779e3cb0064694dae80 Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 58/65] [FS] isolated fs null pointer fix Signed-off-by: di --- kernel/process/syscall.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 7ccbaa42..ddd5e448 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -349,7 +349,7 @@ u64 syscall_openf(process_t *ctx, thread_t *current_thread){ SYSCALL_ARG(file,descriptor,PROC_X1, true); module_root rootfs = {}; string s = resolve_isolated_path(path, ctx->permissions.fs_id, &rootfs, ISOLATEDFS_ALLOW_KFS); - if (!s.data || !s.length) return 0; + if (!s.data || !s.length || !rootfs.map) return 0; FS_RESULT res = open_file(&rootfs, s.data, descriptor); string_free(s); return res; @@ -426,6 +426,7 @@ u64 syscall_dir_list(process_t *ctx, thread_t *current_thread){ #ifdef ISOLATEDFS module_root rootfs = {}; string s = resolve_isolated_path(path, ctx->permissions.fs_id, &rootfs, ISOLATEDFS_ALLOW_KFS); + if (!rootfs.map) return 0; if (!s.data || !s.length || strncmp(s.data,"/",s.length) == 0){ size_t ret = 0; fs_dir_list_helper helper = create_dir_list_helper(buf, size); From 79cfce4b2d48c117abe854188f9e50d7fcb7b57e Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 59/65] [SCHEDULER] syscall return fix Signed-off-by: di --- kernel/process/scheduler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index c51a8e6e..e1bcc495 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -178,7 +178,7 @@ void switch_proc(ProcSwitchReason reason) { void save_syscall_return(uint64_t value){ if (!current_proc) return; - current_proc->main_thread.PROC_X0 = value; + get_current_thread()->PROC_X0 = value; } void process_restore(){ @@ -252,7 +252,7 @@ void ready_process(process_t *proc){ return; } - proc->spsr = proc->main_thread.spsr;//TODO: remove + proc->spsr = proc->main_thread.spsr; enqueue_ready_thread(&proc->main_thread); proc->state = READY; From 8e73f593d30aeac66fec6c31536cd8b77431e95d Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 60/65] [SYSCALL] interrupt syscalls for jobs Signed-off-by: di --- kernel/filesystem/filesystem.c | 12 +-- kernel/process/jobs/job_manager.c | 66 ++++++++++++++++- kernel/process/jobs/job_manager.h | 21 ++++-- kernel/process/jobs/job_save.S | 119 ++++++++++++++++++++++++++++++ kernel/process/scheduler.c | 2 +- kernel/process/syscall.c | 4 +- 6 files changed, 207 insertions(+), 17 deletions(-) create mode 100644 kernel/process/jobs/job_save.S diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index 06d5810c..e15488b1 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -60,7 +60,7 @@ FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor job_serialize_str(&app, 0, search_path); job_serialize_fd(&app, 1, descriptor, copy_on_end); }); - return 0; + return j_ret; } else { result = mod->open(search_path, descriptor); } @@ -132,7 +132,7 @@ size_t read_file(file *descriptor, char* buf, size_t size){ job_serialize_fd(&app, 0, &gfd, copy_on_start); job_serialize_buf(&app, 1, true, (void*)buf, size, copy_on_end); }); - return amount_read; + return j_ret; } else { amount_read = local.mod->read(&gfd, buf, size, start_cursor); } @@ -198,7 +198,7 @@ size_t write_file(file *descriptor, const char* buf, size_t size){ job_serialize_fd(&app, 0, &gfd, copy_on_start); job_serialize_buf(&app, 1, true, (void*)buf, size, copy_on_start); }); - return amount_written; + return j_ret; } else { amount_written = local.mod->write(&gfd, buf, size, 0); } @@ -262,7 +262,7 @@ size_t list_directory_contents(module_root *root, const char *path, void* buf, s job_serialize_buf(&app, 1, true, buf, size, copy_on_end); job_serialize_off(&app, 3, offset); }); - return 0; + return j_ret; } else return mod->readdir(search_path, buf, size, offset); } @@ -285,7 +285,7 @@ bool get_stat(module_root *root, const char *path, fs_stat *out_stat){ job_serialize_str(&app, 0, search_path); job_serialize_stat(&app, 1, out_stat); }) - return false; + return j_ret; } return mod->getstat(search_path, out_stat); } @@ -314,7 +314,7 @@ bool truncate(file *descriptor, size_t size){ job_make(job_trunc, local.mod, { job_serialize_fd(&app, 0, &gfd, copy_on_start); }); - return false; + return j_ret; } else if (!local.mod->truncate(&gfd)) return false; descriptor->size = gfd.size; diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index f87cec3f..5fc48f1f 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -9,9 +9,17 @@ job_id_t job_id_counter = 1; +uptr job_kpec = 0; +sizedptr job_kstack = {}; +extern int syscall_depth; +extern void job_restore_kernel(); +extern uptr job_save_ret(); + typedef struct { thread_t *requester; thread_t *worker; + thread_t kernel_ctx; + sizedptr kstack; job_id_t id; job_buffer buffers[8]; size_t buffer_count; @@ -80,7 +88,7 @@ bool prepare_thread(job_state_t *job, system_module *mod, job_application_t appl return true; } -job_id_t create_new_job(job_application_t application, system_module *mod){ +job_id_t create_new_job(job_application_t application, system_module *mod, thread_t *kthread){ process_t *requesting_proc = get_proc_by_pid(application.requesting_pid); if (!requesting_proc){ print("[JOB error] Unknown requesting proc %i",application.requesting_pid); @@ -102,7 +110,18 @@ job_id_t create_new_job(job_application_t application, system_module *mod){ job->worker = new_t; requester->state = BLOCKED; requesting_proc->state = BLOCKED; + if (syscall_depth >= 1){ + print("[JOB debug] kstack has been saved to %llx - %x",job_kstack.ptr,job_kstack.size); + memcpy(&job->kernel_ctx, kthread, sizeof(thread_t)); + for (u64 i = 0; i < sizeof(thread_t); i+=8){ + print("%i = %llx",i/8,((u64*)kthread)[i]); + } + job->kernel_ctx.job_id = job->id; + job->kernel_ctx.pc = job_save_ret(); + job->kstack = job_kstack; + } else memset(&job->kernel_ctx, 0, sizeof(thread_t)); schedule_thread(fs_owner, new_t); + switch_proc(YIELD); return job->id; } @@ -127,6 +146,12 @@ void* quick_translate(thread_t *thread, process_t *proc, uptr ptr){ return (void*)PHYS_TO_VIRT(addr); } +extern uptr cpec; + +static inline uptr translate_stack(uptr new_top, uptr ptr){ + return new_top-((uptr)ksp-ptr); +} + void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ job_state_t *st = get_job_state(job_id); if (!st) { @@ -138,8 +163,6 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ return; } process_t *proc = get_proc_by_pid(st->requester->pid); - ready_thread(st->requester); - st->requester->PROC_X0 = ret; for (size_t i = 0; i < st->buffer_count; i++){ job_buffer buf = st->buffers[i]; if (buf.sync & copy_on_end && buf.worker_ptr.ptr){ @@ -157,4 +180,41 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ } } print("[JOB] %i fulfilled by %i",job_id,thread->tid); + if (st->kernel_ctx.job_id){ + //Restore kernel proc here and let it return to the process + print("Restoring to kernel's functionality here %llx",st->kernel_ctx.pc); + st->kernel_ctx.PROC_X0 = ret; + job_kpec = (uptr)&st->kernel_ctx; + cpec = (uptr)st->requester; + // print("Kernel will restore to %i %i. with %llx of stack being restored to %llx from %llx",st->requester->pid,st->requester->tid,st->kstack.size,ksp,st->kstack.ptr); + // print("memcpy(%llx,%llx,%llx)",ksp-st->kstack.size,st->kstack.ptr,st->kstack.size); + // memcpy(ksp-st->kstack.size, (void*)st->kstack.ptr, st->kstack.size); + + + // print("SP is %llx and LR is %llx",st->kernel_ctx.sp,st->kernel_ctx.regs[29]); + + st->kernel_ctx.sp = translate_stack((st->kstack.ptr+st->kstack.size), st->kernel_ctx.sp); + print("Initial Address %llx",st->kernel_ctx.regs[29]); + st->kernel_ctx.regs[29] = translate_stack((st->kstack.ptr+st->kstack.size), st->kernel_ctx.regs[29]); + + uptr addr = st->kernel_ctx.regs[29]; + uptr fp = 0; + do { + print("Address %llx",addr); + fp = *(uptr*)addr; + print("Link %llx",fp); + fp = translate_stack(fp, st->kstack.ptr+st->kstack.size); + print("In new stack %llx",fp); + *(uptr*)addr = fp; + addr = fp; + } while(addr && (addr & 0xfffff00000000000) == 0xffffc00000000000); + + job_restore_kernel(); + + // st->kernel_ctx.sp = st->kstack.ptr-((uptr)ksp-st->kernel_ctx.sp); + // job_restore_kernel(); + } else { + ready_thread(st->requester); + st->requester->PROC_X0 = ret; + } } \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index 7ddb91df..5ae0627d 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -3,10 +3,20 @@ #include "files/jobs.h" #include "process/process.h" +extern uptr job_kpec; +extern sizedptr job_kstack; +extern void job_save_kernel(); +extern void save_kstack(); + //TODO: if the owner is the current process, we can downgrade the syscall into a function call without async #define job_make(job_type,mod,action)\ -process_t *owner_proc = get_proc_by_pid(mod->owner);\ -if (!is_privileged(owner_proc)){\ + thread_t kthread = {};\ + job_kpec = (uptr)&kthread;\ + job_save_kernel();\ + print("KStack save");\ + save_kstack();\ + print("KStack saved to %llx of size %llx from %llx",job_kstack.ptr,job_kstack.size,ksp);\ + process_t *owner_proc = get_proc_by_pid(mod->owner);\ job_application_t app = (job_application_t){\ .requesting_pid = get_current_proc()->id,\ .requesting_tid = get_current_thread()->tid,\ @@ -14,9 +24,8 @@ if (!is_privileged(owner_proc)){\ .type = job_type\ };\ action\ - create_new_job(app,mod);\ - switch_proc(YIELD);\ -} + u64 j_ret = create_new_job(app, mod, &kthread);\ + (void)j_ret; static inline void job_application_append_buffer(job_application_t *app, job_buffer buf){ if (app->buffer_count >= MAX_JOB_BUFFERS) return; @@ -80,5 +89,5 @@ static inline void job_serialize_off(job_application_t *application, int arg_num job_application_append_buffer(application, buf); } -job_id_t create_new_job(job_application_t application, system_module *mod); +job_id_t create_new_job(job_application_t application, system_module *mod, thread_t *kthread); void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread); diff --git a/kernel/process/jobs/job_save.S b/kernel/process/jobs/job_save.S new file mode 100644 index 00000000..3120a896 --- /dev/null +++ b/kernel/process/jobs/job_save.S @@ -0,0 +1,119 @@ +.global job_save_kernel +job_save_kernel: + msr daifset, #2 + + stp x17, x18, [sp, #-16]! + add x17, sp, #16 +2: + adrp x18, job_kpec + add x18, x18, :lo12:job_kpec + ldr x18, [x18] + +3: + +// Save general-purpose registers x1-x30 +stp x0, x1, [x18, #(8 * 0)] +stp x2, x3, [x18, #(8 * 2)] +stp x4, x5, [x18, #(8 * 4)] +stp x6, x7, [x18, #(8 * 6)] +stp x8, x9, [x18, #(8 * 8)] +stp x10, x11, [x18, #(8 * 10)] +stp x12, x13, [x18, #(8 * 12)] +stp x14, x15, [x18, #(8 * 14)] +str x16, [x18, #(8 * 16)] +ldr x16, [sp, #0] +str x16, [x18, #(8 * 17)] +ldr x16, [sp, #8] +str x16, [x18, #(8 * 18)] +str x19, [x18, #(8 * 19)] +stp x20, x21, [x18, #(8 * 20)] +stp x22, x23, [x18, #(8 * 22)] +stp x24, x25, [x18, #(8 * 24)] +stp x26, x27, [x18, #(8 * 26)] +stp x28, x29, [x18, #(8 * 28)] +str x30, [x18,#(8 * 30)] + +// SP +str x17, [x18, #(8 * 31)] + +//Status bits +mrs x17, spsr_el1 +str x17, [x18, #(8 * 33)] + +add sp, sp, #16 + +ret + +.global save_kstack +save_kstack: + +sub sp, sp, #32 +stp x0, x1, [sp, #0] +stp x21,x30, [sp, #16] + +adrp x0, ksp +add x0, x0, :lo12:ksp + +mov x1, sp +sub x21, x0, x1 +mov x0, #0x10000 +bl zalloc + +adrp x1, job_kstack +add x1, x1, :lo12:job_kstack +stp x0, x21, [x1, #0] + +mov x1, sp +mov x2, x21 +bl memcpy + +ldp x0, x1, [sp, #0] +ldp x21,x30, [sp, #16] + +add sp, sp, #32 + +ret + +.global job_restore_kernel +job_restore_kernel: + adrp x18, job_kpec + add x18, x18, :lo12:job_kpec + ldr x18, [x18] + // Restore general-purpose registers + ldp x0, x1, [x18, #(8 * 0)] + ldp x2, x3, [x18, #(8 * 2)] + ldp x4, x5, [x18, #(8 * 4)] + ldp x6, x7, [x18, #(8 * 6)] + ldp x8, x9, [x18, #(8 * 8)] + ldp x10, x11, [x18, #(8 * 10)] + ldp x12, x13, [x18, #(8 * 12)] + ldp x14, x15, [x18, #(8 * 14)] + ldr x16, [x18, #(8 * 16)] + ldr x19, [x18, #(8 * 19)] + ldp x20, x21, [x18, #(8 * 20)] + ldp x22, x23, [x18, #(8 * 22)] + ldp x24, x25, [x18, #(8 * 24)] + ldp x26, x27, [x18, #(8 * 26)] + ldp x28, x29, [x18, #(8 * 28)] + ldr x30, [x18, #(8 * 30)] + + ldr x17, [x18, #(8 * 33)] + msr spsr_el1, x17 + lsr x17, x17, #2 + and x17, x17, #0b11 + + ldr x17, [x18, #(8 * 31)] + mov sp, x17 + + ldr x17, [x18, #(8 * 17)] + ldr x30, [x18, #(8 * 32)] + ldr x18, [x18, #(8 * 18)] + + ret + +.global job_save_ret +job_save_ret: + ldr x0, [sp, #8] + + ret + diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index e1bcc495..3bafc3fa 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -125,6 +125,7 @@ void update_sleep_timer() { } void switch_proc(ProcSwitchReason reason) { + syscall_depth = 0; if (proc_count == 0) panic("No processes active", 0); thread_t *prev_t = (thread_t*)cpec; @@ -134,7 +135,6 @@ void switch_proc(ProcSwitchReason reason) { else if (prev_t->state == RUNNING) enqueue_ready_thread(prev_t); } - thread_t *next_thread = 0; while (!cqueue_is_empty(&ready_queue)) { thread_t *queued = 0; diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index ddd5e448..bf5f62b8 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -454,7 +454,9 @@ u64 syscall_stat(process_t *ctx, thread_t *current_thread){ if (!s.data || !s.length){ return root_stat(path, out_stat); } + kprintf("String before syscall %llx",s.data); size_t ret = get_stat(&rootfs, s.data, out_stat); + kprintf("String after syscall %llx",s.data); string_free(s); return ret; #else @@ -683,9 +685,9 @@ void sync_el0_handler_c(){ } else { if (currentEL == 1){ if (syscall_depth < 3){ - kprintf("System has crashed. ESR: %llx. ELR: %llx. FAR: %llx", esr, elr, far); uint64_t ksp = 0; asm volatile ("mov %0, sp" : "=r"(ksp)); + kprintf("System has crashed. ESR: %llx. ELR: %llx. FAR: %llx. KSP: %llx", esr, elr, far, ksp); coredump(esr, elr, far, ksp); } handle_exception("UNEXPECTED EXCEPTION", ec); From 8b9d3281611b28a2747d5aac798ddea7cb95e174 Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 61/65] [JOB] reschedule thread Signed-off-by: di --- kernel/process/jobs/job_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 5fc48f1f..c2a1cfa8 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -208,7 +208,7 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ *(uptr*)addr = fp; addr = fp; } while(addr && (addr & 0xfffff00000000000) == 0xffffc00000000000); - + ready_thread(st->requester); job_restore_kernel(); // st->kernel_ctx.sp = st->kstack.ptr-((uptr)ksp-st->kernel_ctx.sp); From 3c16bb52f3563812c36f3c7afbcb63d006c03371 Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 62/65] [JOB] cleanup logs and return type [SCHEDULE] prepare process separate from restore Signed-off-by: di --- kernel/process/jobs/job_manager.c | 11 ++++------- kernel/process/jobs/job_manager.h | 2 +- kernel/process/scheduler.c | 24 ++++++++++++++---------- kernel/process/scheduler.h | 1 + kernel/process/syscall.c | 9 +++++---- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index c2a1cfa8..c9b00c1b 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -88,7 +88,7 @@ bool prepare_thread(job_state_t *job, system_module *mod, job_application_t appl return true; } -job_id_t create_new_job(job_application_t application, system_module *mod, thread_t *kthread){ +u64 create_new_job(job_application_t application, system_module *mod, thread_t *kthread){ process_t *requesting_proc = get_proc_by_pid(application.requesting_pid); if (!requesting_proc){ print("[JOB error] Unknown requesting proc %i",application.requesting_pid); @@ -109,20 +109,16 @@ job_id_t create_new_job(job_application_t application, system_module *mod, threa new_t->job_id = job->id; job->worker = new_t; requester->state = BLOCKED; - requesting_proc->state = BLOCKED; if (syscall_depth >= 1){ print("[JOB debug] kstack has been saved to %llx - %x",job_kstack.ptr,job_kstack.size); memcpy(&job->kernel_ctx, kthread, sizeof(thread_t)); - for (u64 i = 0; i < sizeof(thread_t); i+=8){ - print("%i = %llx",i/8,((u64*)kthread)[i]); - } job->kernel_ctx.job_id = job->id; job->kernel_ctx.pc = job_save_ret(); job->kstack = job_kstack; } else memset(&job->kernel_ctx, 0, sizeof(thread_t)); schedule_thread(fs_owner, new_t); switch_proc(YIELD); - return job->id; + return 0; } job_state_t* get_job_state(job_id_t job_id){ @@ -208,7 +204,8 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ *(uptr*)addr = fp; addr = fp; } while(addr && (addr & 0xfffff00000000000) == 0xffffc00000000000); - ready_thread(st->requester); + st->requester->state = RUNNING; + prepare_process_restore(proc); job_restore_kernel(); // st->kernel_ctx.sp = st->kstack.ptr-((uptr)ksp-st->kernel_ctx.sp); diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index 5ae0627d..d300df45 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -89,5 +89,5 @@ static inline void job_serialize_off(job_application_t *application, int arg_num job_application_append_buffer(application, buf); } -job_id_t create_new_job(job_application_t application, system_module *mod, thread_t *kthread); +u64 create_new_job(job_application_t application, system_module *mod, thread_t *kthread); void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread); diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 3bafc3fa..1d0aba7a 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -181,24 +181,28 @@ void save_syscall_return(uint64_t value){ get_current_thread()->PROC_X0 = value; } -void process_restore(){ - if (!current_proc) panic("process_restore null process", 0); - if (!process_is_known(current_proc)) panic("process_restore unknown process", cpec); - if (current_proc->pending_reset || current_proc->state == STOPPED || !current_proc->main_thread.pc || !current_proc->main_thread.sp) { - if (current_proc->mm.ttbr0) { - current_proc->pending_reset = true; - current_proc->state = STOPPED; +void prepare_process_restore(process_t *proc){ + if (!proc) panic("process_restore null process", 0); + if (!process_is_known(proc)) panic("process_restore unknown process", cpec); + if (proc->pending_reset || proc->state == STOPPED || !proc->main_thread.pc || !proc->main_thread.sp) { + if (proc->mm.ttbr0) { + proc->pending_reset = true; + proc->state = STOPPED; switch_proc(HALT); panic("process_restore recovery returned", cpec); } panic("process_restore invalid process", cpec); } - if (!is_privileged(current_proc)) { - if (!current_proc->mm.ttbr0) panic("process_restore user process without ttbr0", current_proc->id); - if (current_proc->main_thread.pc >= HIGH_VA) panic("user pc in kernel VA", current_proc->main_thread.pc); + if (!is_privileged(proc)) { + if (!proc->mm.ttbr0) panic("process_restore user process without ttbr0", proc->id); + if (proc->main_thread.pc >= HIGH_VA) panic("user pc in kernel VA", proc->main_thread.pc); mmu_ttbr0_enable_user(); } else mmu_ttbr0_disable_user(); +} + +void process_restore(){ + prepare_process_restore(current_proc); restore_context(cpec); } diff --git a/kernel/process/scheduler.h b/kernel/process/scheduler.h index 32b56958..01d7f99e 100644 --- a/kernel/process/scheduler.h +++ b/kernel/process/scheduler.h @@ -30,6 +30,7 @@ process_t* init_process(); void ready_process(process_t *proc); void ready_thread(thread_t *t); void save_syscall_return(uint64_t value); +void prepare_process_restore(process_t *proc); void process_restore(); void stop_process(uint16_t pid, int32_t exit_code); diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index bf5f62b8..a9b74cf1 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -434,7 +434,10 @@ u64 syscall_dir_list(process_t *ctx, thread_t *current_thread){ ret += list_root_from(&rootfs, &helper, offset); } if (ret >= size) return ret; + //TODO: this calculation needs to make the offsets relative for each root mod +#if ISOLATEDFS_ALLOW_KFS ret += list_root_from(kernel_fs(), &helper, offset); +#endif return ret; } size_t ret = list_directory_contents(&rootfs, s.data, buf, size, offset); @@ -454,9 +457,7 @@ u64 syscall_stat(process_t *ctx, thread_t *current_thread){ if (!s.data || !s.length){ return root_stat(path, out_stat); } - kprintf("String before syscall %llx",s.data); size_t ret = get_stat(&rootfs, s.data, out_stat); - kprintf("String after syscall %llx",s.data); string_free(s); return ret; #else @@ -693,8 +694,8 @@ void sync_el0_handler_c(){ handle_exception("UNEXPECTED EXCEPTION", ec); while (true); } else { - kprintf("Process has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", esr, elr, far, current_thread->sp); - if (syscall_depth <= 2) coredump(esr, elr, far, current_thread->sp); + kprintf("Process [p: %i t: %i] has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", current_thread->pid,current_thread->tid, esr, elr, far, current_thread->sp); + coredump(esr, elr, far, current_thread->sp); syscall_depth--; stop_current_process(ec); } From 0f223e9d7df22a8dc298a17861cf6f036d7f400a Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 63/65] [JOB] properly restore process Signed-off-by: di --- kernel/process/jobs/job_manager.c | 11 ----------- kernel/process/scheduler.c | 3 +++ kernel/process/syscall.c | 1 + 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index c9b00c1b..f1700c2d 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -177,17 +177,9 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ } print("[JOB] %i fulfilled by %i",job_id,thread->tid); if (st->kernel_ctx.job_id){ - //Restore kernel proc here and let it return to the process - print("Restoring to kernel's functionality here %llx",st->kernel_ctx.pc); st->kernel_ctx.PROC_X0 = ret; job_kpec = (uptr)&st->kernel_ctx; cpec = (uptr)st->requester; - // print("Kernel will restore to %i %i. with %llx of stack being restored to %llx from %llx",st->requester->pid,st->requester->tid,st->kstack.size,ksp,st->kstack.ptr); - // print("memcpy(%llx,%llx,%llx)",ksp-st->kstack.size,st->kstack.ptr,st->kstack.size); - // memcpy(ksp-st->kstack.size, (void*)st->kstack.ptr, st->kstack.size); - - - // print("SP is %llx and LR is %llx",st->kernel_ctx.sp,st->kernel_ctx.regs[29]); st->kernel_ctx.sp = translate_stack((st->kstack.ptr+st->kstack.size), st->kernel_ctx.sp); print("Initial Address %llx",st->kernel_ctx.regs[29]); @@ -207,9 +199,6 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ st->requester->state = RUNNING; prepare_process_restore(proc); job_restore_kernel(); - - // st->kernel_ctx.sp = st->kstack.ptr-((uptr)ksp-st->kernel_ctx.sp); - // job_restore_kernel(); } else { ready_thread(st->requester); st->requester->PROC_X0 = ret; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 1d0aba7a..8479f75b 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -182,6 +182,7 @@ void save_syscall_return(uint64_t value){ } void prepare_process_restore(process_t *proc){ + current_proc = proc; if (!proc) panic("process_restore null process", 0); if (!process_is_known(proc)) panic("process_restore unknown process", cpec); if (proc->pending_reset || proc->state == STOPPED || !proc->main_thread.pc || !proc->main_thread.sp) { @@ -195,8 +196,10 @@ void prepare_process_restore(process_t *proc){ } if (!is_privileged(proc)) { + // print("Restoring process %i ttbr0",proc->id); if (!proc->mm.ttbr0) panic("process_restore user process without ttbr0", proc->id); if (proc->main_thread.pc >= HIGH_VA) panic("user pc in kernel VA", proc->main_thread.pc); + mmu_swap_ttbr(&proc->mm); mmu_ttbr0_enable_user(); } else mmu_ttbr0_disable_user(); } diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index a9b74cf1..997c3d82 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -702,6 +702,7 @@ void sync_el0_handler_c(){ } syscall_depth--; save_syscall_return(result); + // print("Return to %i",current_thread->pid); process_restore(); } From 717b5d75d729d534d3a6f5eb485ebdf0dd877b25 Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 64/65] [JOB] proper stack management Signed-off-by: di --- kernel/process/jobs/job_manager.c | 34 +++++++++++++++++-------------- kernel/process/jobs/job_manager.h | 5 ++++- kernel/process/jobs/job_save.S | 15 ++++++++++++-- kernel/process/scheduler.c | 3 +++ 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index f1700c2d..f242f887 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -10,6 +10,7 @@ job_id_t job_id_counter = 1; uptr job_kpec = 0; +uptr job_ksp = 0; sizedptr job_kstack = {}; extern int syscall_depth; extern void job_restore_kernel(); @@ -181,23 +182,26 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ job_kpec = (uptr)&st->kernel_ctx; cpec = (uptr)st->requester; - st->kernel_ctx.sp = translate_stack((st->kstack.ptr+st->kstack.size), st->kernel_ctx.sp); - print("Initial Address %llx",st->kernel_ctx.regs[29]); - st->kernel_ctx.regs[29] = translate_stack((st->kstack.ptr+st->kstack.size), st->kernel_ctx.regs[29]); - - uptr addr = st->kernel_ctx.regs[29]; - uptr fp = 0; - do { - print("Address %llx",addr); - fp = *(uptr*)addr; - print("Link %llx",fp); - fp = translate_stack(fp, st->kstack.ptr+st->kstack.size); - print("In new stack %llx",fp); - *(uptr*)addr = fp; - addr = fp; - } while(addr && (addr & 0xfffff00000000000) == 0xffffc00000000000); + if (st->kstack.ptr){ + st->kernel_ctx.sp = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.sp); + print("[JOB debug] Initial Address %llx",st->kernel_ctx.regs[29]); + st->kernel_ctx.regs[29] = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.regs[29]); + + uptr addr = st->kernel_ctx.regs[29]; + uptr fp = 0; + do { + print("[JOB debug] Address %llx",addr); + fp = *(uptr*)addr; + print("[JOB debug] Link %llx",fp); + fp = translate_stack(st->kstack.ptr+0x10000, fp); + print("[JOB debug] In new stack %llx",fp); + *(uptr*)addr = fp; + addr = fp; + } while(addr && (addr & 0xfffff00000000000) == 0xffffc00000000000); + } st->requester->state = RUNNING; prepare_process_restore(proc); + job_ksp = st->kstack.ptr+0x10000; job_restore_kernel(); } else { ready_thread(st->requester); diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index d300df45..f8842116 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -4,6 +4,7 @@ #include "process/process.h" extern uptr job_kpec; +extern uptr job_ksp; extern sizedptr job_kstack; extern void job_save_kernel(); extern void save_kstack(); @@ -11,9 +12,11 @@ extern void save_kstack(); //TODO: if the owner is the current process, we can downgrade the syscall into a function call without async #define job_make(job_type,mod,action)\ thread_t kthread = {};\ + job_kstack = (sizedptr){};\ job_kpec = (uptr)&kthread;\ + if (!job_ksp) job_ksp = (uptr)ksp;\ job_save_kernel();\ - print("KStack save");\ + print("KStack save to %llx",job_ksp);\ save_kstack();\ print("KStack saved to %llx of size %llx from %llx",job_kstack.ptr,job_kstack.size,ksp);\ process_t *owner_proc = get_proc_by_pid(mod->owner);\ diff --git a/kernel/process/jobs/job_save.S b/kernel/process/jobs/job_save.S index 3120a896..2cbfbb58 100644 --- a/kernel/process/jobs/job_save.S +++ b/kernel/process/jobs/job_save.S @@ -51,8 +51,15 @@ sub sp, sp, #32 stp x0, x1, [sp, #0] stp x21,x30, [sp, #16] -adrp x0, ksp -add x0, x0, :lo12:ksp +adrp x0, job_ksp +add x0, x0, :lo12:job_ksp +ldr x0, [x0] + +adrp x1, ksp +add x1, x1, :lo12:ksp +cmp x0, x1 + +b.ne 2f mov x1, sp sub x21, x0, x1 @@ -63,10 +70,14 @@ adrp x1, job_kstack add x1, x1, :lo12:job_kstack stp x0, x21, [x1, #0] +add x0,x0,#0x10000 +sub x0,x0,x21 + mov x1, sp mov x2, x21 bl memcpy +2: ldp x0, x1, [sp, #0] ldp x21,x30, [sp, #16] diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 8479f75b..5bab0b64 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -124,6 +124,8 @@ void update_sleep_timer() { } else virtual_timer_disable(); } +extern uptr job_ksp; + void switch_proc(ProcSwitchReason reason) { syscall_depth = 0; if (proc_count == 0) @@ -173,6 +175,7 @@ void switch_proc(ProcSwitchReason reason) { mmu_swap_ttbr(current_proc->mm.ttbr0 ? ¤t_proc->mm : 0); if (prev && prev != current_proc && prev != idle_proc && process_can_reset(prev)) reset_process(prev); + job_ksp = (uptr)ksp; process_restore(); } From 6a5a4ad8ee8ae4842d6d7792aaab4e7e5b73e3a4 Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 65/65] [THREADING] alternate kstack cleanup todo Signed-off-by: di --- kernel/process/jobs/job_manager.c | 1 + kernel/process/process.h | 1 + kernel/process/syscall.c | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index f242f887..7878d6e8 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -99,6 +99,7 @@ u64 create_new_job(job_application_t application, system_module *mod, thread_t * job->type = application.type; job->mod = mod; thread_t *requester = (thread_t*)get_thread_from_proc(requesting_proc, application.requesting_tid); + if (job_ksp != (uptr)ksp) requester->kstack_top = job_ksp; job->requester = requester; process_t *fs_owner = get_proc_by_pid(application.worker_pid); thread_t *new_t = alloc_thread(); diff --git a/kernel/process/process.h b/kernel/process/process.h index 9a6f5ec3..b1a2a2cf 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -72,6 +72,7 @@ struct thread_t { uint64_t spsr; //Not used in context saving stack_t stack_info; + uptr kstack_top; u16 pid; u16 tid; process_state state; diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 997c3d82..87739089 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -703,6 +703,10 @@ void sync_el0_handler_c(){ syscall_depth--; save_syscall_return(result); // print("Return to %i",current_thread->pid); + if (current_thread->kstack_top) { + //TODO: schedule kstack_top to cleanup, but don't do immediately as we're in it + current_thread->kstack_top = 0; + } process_restore(); }