From ada9a47d3fdba3567db375ae26be74cfcd0746dc Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 28 Dec 2025 22:06:49 -0500 Subject: [PATCH 01/38] Start including apps elf build --- src/apps/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/CMakeLists.txt b/src/apps/CMakeLists.txt index bb97f8c..a0c0df1 100644 --- a/src/apps/CMakeLists.txt +++ b/src/apps/CMakeLists.txt @@ -8,6 +8,7 @@ macro(add_app target) add_custom_command(OUTPUT ${APPS_BASE_DIR}/${target} COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/${target}.bin ${APPS_BASE_DIR}/${target} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/${target}.elf ${APPS_BASE_DIR}/${target}.elf DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${target}.bin) add_custom_target(${target}_app From ec05593e783be01f1280f73b4b38c4cc5cd48058 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Thu, 1 Jan 2026 01:43:46 -0500 Subject: [PATCH 02/38] Add vga to vm --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index bc3780c..e2f9ca1 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ QEMUFLAGS = -m 1G \ -drive format=raw,file=build/os-image.bin,index=0,if=floppy \ -drive format=raw,file=build/apps.tar \ -d int,mmu \ + -vga cirrus \ -D qemu_log.txt \ -no-reboot -no-shutdown \ -chardev stdio,id=char0,logfile=kernel.log,signal=off -serial chardev:char0 From c9d646959d1328c69b30a2241054ab92d579fa9f Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 25 Jan 2026 21:36:07 -0500 Subject: [PATCH 03/38] More error handling --- .github/workflows/ci.yml | 7 +- src/kernel/include/paging.h | 6 +- src/kernel/src/drivers/ram.c | 81 ++++++++-- src/kernel/src/drivers/serial.c | 2 + src/kernel/src/exec.c | 149 ++++++++++++++++-- src/kernel/src/kernel.c | 19 ++- src/kernel/src/kernel/panic.c | 5 +- src/kernel/src/loader.c | 73 +++++++-- src/kernel/src/paging.c | 166 ++++++++++++++++---- src/kernel/src/process.c | 213 ++++++++++++++++++++++---- src/kernel/src/process_manager.c | 93 +++++++++-- tests/src/mocks/include/paging.mock.h | 4 +- tests/src/mocks/src/paging.mock.c | 4 +- 13 files changed, 696 insertions(+), 126 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3da3cc9..e394303 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,9 +34,10 @@ jobs: - name: Build run: cmake --build ${BUILD_DIR} - - name: Test - working-directory: build - run: ctest -V + # TODO reenable testing once arch. is stable again + # - name: Test + # working-directory: build + # run: ctest -V # TODO re-enable this once coverage is complete # - name: Test with Coverage diff --git a/src/kernel/include/paging.h b/src/kernel/include/paging.h index 73cda47..ea80ae6 100644 --- a/src/kernel/include/paging.h +++ b/src/kernel/include/paging.h @@ -8,8 +8,9 @@ /** * @brief Setup paging called by kernel main. + * @return int 0 for success */ -void paging_init(); +int paging_init(); /** * @brief Map `paddr` to a temporary page and return the virtual address. @@ -30,8 +31,9 @@ void * paging_temp_map(uint32_t paddr); * until empty. * * @param paddr physical address to free + * @return int 0 for success */ -void paging_temp_free(uint32_t paddr); +int paging_temp_free(uint32_t paddr); /** * @brief Get count of free pages for temporary mapping. diff --git a/src/kernel/src/drivers/ram.c b/src/kernel/src/drivers/ram.c index 38e5797..081a3da 100644 --- a/src/kernel/src/drivers/ram.c +++ b/src/kernel/src/drivers/ram.c @@ -17,14 +17,14 @@ static ram_table_t * __region_table; static size_t __region_table_count; static void * __bitmask; -static int find_addr_entry(uint32_t addr, size_t * out_bit_i); -static int find_free_bit(const void * bitmask, size_t page_count); -static int find_free_region(); -static void set_bit_used(void * bitmask, size_t bit); -static void set_bit_free(void * bitmask, size_t bit); -static int is_bit_free(void * bitmask, size_t bit); -static void fill_bitmask(void * bitmask, size_t page_count); -static void add_memory_at(size_t start, uint64_t base, uint64_t length); +static int find_addr_entry(uint32_t addr, size_t * out_bit_i); +static int find_free_bit(const void * bitmask, size_t page_count); +static int find_free_region(); +static int set_bit_used(void * bitmask, size_t bit); +static int set_bit_free(void * bitmask, size_t bit); +static int is_bit_free(void * bitmask, size_t bit); +static int fill_bitmask(void * bitmask, size_t page_count); +static int add_memory_at(size_t start, uint64_t base, uint64_t length); int ram_init(ram_table_t * ram_table, void * bitmasks) { if (!ram_table) { @@ -211,7 +211,7 @@ int ram_page_free(uint32_t addr) { void * bitmask = __bitmask + PAGE_SIZE * region_i; if (is_bit_free(bitmask, bit_i)) { - KLOG_ERROR("Page %u in region %d for address 0x%XX is already free", bit_i, region_i, addr); + KLOG_ERROR("Page %u in region %d for address 0x%X is already free", bit_i, region_i, addr); return -1; } @@ -224,6 +224,14 @@ int ram_page_free(uint32_t addr) { } static int find_addr_entry(uint32_t addr, size_t * out_bit_i) { + if (!addr) { + KLOG_ERROR("Searching for null address"); + return -1; + } + if (!out_bit_i) { + KLOG_ERROR("Output pointer is null"); + return -1; + } for (size_t i = 0; i < __region_table_count; i++) { ram_table_entry_t * entry = &__region_table->entries[i]; @@ -237,10 +245,20 @@ static int find_addr_entry(uint32_t addr, size_t * out_bit_i) { } } + KLOG_ERROR("Failed to find entry for address %p", addr); + return -1; } static int find_free_bit(const void * bitmask, size_t page_count) { + if (!bitmask) { + KLOG_ERROR("Tried to find bitmask of null pointer"); + return -1; + } + if (!page_count) { + KLOG_WARNING("Trying to find free bit form 0 pages"); + return -1; + } const char * bitmask_data = bitmask; for (size_t i = 1; i < page_count; i++) { @@ -252,6 +270,8 @@ static int find_free_bit(const void * bitmask, size_t page_count) { } } + KLOG_ERROR("Failed to find free bit in bitmask %p", bitmask); + return -1; } @@ -264,28 +284,49 @@ static int find_free_region() { } } + KLOG_ERROR("Failed to find free region"); + return -1; } -static void set_bit_used(void * bitmask, size_t bit) { +static int set_bit_used(void * bitmask, size_t bit) { + if (!bitmask) { + KLOG_ERROR("Tried to set used bit of null bitmask"); + return -1; + } + char * bitmask_data = bitmask; size_t byte = bit / 8; bit = bit % 8; bitmask_data[byte] &= ~(1 << bit); + + return 0; } -static void set_bit_free(void * bitmask, size_t bit) { +static int set_bit_free(void * bitmask, size_t bit) { + if (!bitmask) { + KLOG_ERROR("Tried to set free bit of null bitmask"); + return -1; + } + char * bitmask_data = bitmask; size_t byte = bit / 8; bit = bit % 8; bitmask_data[byte] |= 1 << bit; + + return 0; } static int is_bit_free(void * bitmask, size_t bit) { + if (!bitmask) { + KLOG_ERROR("Tried to check if bit is used of null bitmask"); + return 0; + } + char * bitmask_data = bitmask; size_t byte = bit / 8; @@ -302,7 +343,16 @@ static int is_bit_free(void * bitmask, size_t bit) { * @param bitmask pointer to the bitmask * @param page_count number of pages in region including the bitmask page */ -static void fill_bitmask(void * bitmask, size_t page_count) { +static int fill_bitmask(void * bitmask, size_t page_count) { + if (!bitmask) { + KLOG_ERROR("Trying to fill bitmask of null pointer"); + return -1; + } + if (!page_count) { + KLOG_WARNING("Trying to fill bitmask for 0 pages"); + return -1; + } + unsigned char * bitmask_data = (unsigned char *)bitmask; size_t bytes = page_count / 8; @@ -322,9 +372,12 @@ static void fill_bitmask(void * bitmask, size_t page_count) { } bitmask_data[0] &= 0xfe; + + return 0; } -static void add_memory_at(size_t start, uint64_t base, uint64_t length) { +static int add_memory_at(size_t start, uint64_t base, uint64_t length) { + // TODO what are invalid inputs? size_t split_count = length / REGION_MAX_SIZE; for (size_t i = 0; i <= split_count; i++) { @@ -345,4 +398,6 @@ static void add_memory_at(size_t start, uint64_t base, uint64_t length) { base += REGION_MAX_SIZE; } + + return 0; } diff --git a/src/kernel/src/drivers/serial.c b/src/kernel/src/drivers/serial.c index c9402ae..b78c5e1 100644 --- a/src/kernel/src/drivers/serial.c +++ b/src/kernel/src/drivers/serial.c @@ -6,6 +6,8 @@ // WARNING serial driver is used in logging, so be careful about where you log // so you don't get an infinite loop. +// TODO might need to disable interrupts while interacting with ports? + int serial_init(uint16_t port) { port_byte_out(port + 1, 0x00); // Disable all interrupts port_byte_out(port + 3, 0x80); // Enable DLAB (set baud rate divisor) diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index 9fe86bb..f92f031 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -4,6 +4,7 @@ #include "cpu/tss.h" #include "drivers/ram.h" #include "kernel.h" +#include "kernel/logs.h" #include "libc/memory.h" #include "libc/proc.h" #include "libc/stdio.h" @@ -11,38 +12,112 @@ #include "paging.h" #include "process.h" +#undef SERVICE +#define SERVICE "KERNEL/EXEC" + typedef int (*ff_t)(size_t argc, char ** argv); static void proc_entry(); static int copy_args(process_t * proc, const char * filepath, int argc, char ** argv); int command_exec(uint8_t * buff, const char * filepath, size_t size, size_t argc, char ** argv) { + if (!buff) { + KLOG_ERROR("Tried to execute null buffer"); + return -1; + } + if (!filepath) { + KLOG_ERROR("Missing filepath"); + return -1; + } + if (!size) { + KLOG_WARNING("Buffer size is 0"); + } + if (argc && !argv) { + KLOG_ERROR("Missing argv"); + return -1; + } + process_t * proc = kmalloc(sizeof(process_t)); + if (!proc) { + KLOG_ERROR("Failed to malloc process_t"); + return -1; + } process_t * active = get_active_task(); if (process_create(proc)) { - puts("Failed to create process\n"); + KLOG_ERROR("Failed to create process"); + kfree(proc); return -1; } if (process_load_heap(proc, buff, size)) { - puts("Failed to load\n"); - process_free(proc); + KLOG_ERROR("Failed to load heap"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling load heap error"); + } + kfree(proc); return -1; } + KLOG_TRACE("Increasing stack by 1022 pages"); for (size_t i = 0; i < 1022; i++) { - process_grow_stack(proc); + if (process_grow_stack(proc)) { + KLOG_ERROR("Failed to add page %u", i); + if (process_free(proc)) { + KPANIC("Failed to free process while handling stack grow error"); + } + kfree(proc); + return -1; + } + } + + if (copy_args(proc, filepath, argc, argv)) { + KLOG_ERROR("Failed to copy args"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling copy args error"); + } + kfree(proc); + return -1; + } + + KLOG_TRACE("Setting process entrypoint to %p", proc_entry); + + if (process_set_entrypoint(proc, proc_entry)) { + KLOG_ERROR("Failed to set entrypoint"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling set entrypoint error"); + } + kfree(proc); + return -1; } - copy_args(proc, filepath, argc, argv); + KLOG_TRACE("Adding 32 pages"); - process_set_entrypoint(proc, proc_entry); - process_add_pages(proc, 32); - pm_add_proc(kernel_get_proc_man(), proc); + if (!process_add_pages(proc, 32)) { + KLOG_ERROR("Failed to add 32 pages"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling add 32 pages error"); + } + kfree(proc); + return -1; + } + + if (pm_add_proc(kernel_get_proc_man(), proc)) { + KLOG_ERROR("Failed to add process to process manager"); + if (process_free(proc)) { + KPANIC("Failed to free process while handling add process to process manager error"); + } + kfree(proc); + return -1; + } if (pm_resume_process(kernel_get_proc_man(), proc->pid, 0)) { + KLOG_ERROR("Failed to resume process %u", proc->pid); + if (process_free(proc)) { + KPANIC("Failed to free process while handling resume error"); + } + kfree(proc); return -1; } @@ -60,30 +135,78 @@ static void proc_entry() { // TODO get start function pointer from elf + KLOG_TRACE("Entering process pid %u", proc->pid); + int res = fn(proc->argc, proc->argv); proc->status_code = res; + + KLOG_TRACE("Return from process pid %u with status %d", proc->pid, res); } static char * copy_string(const char * str) { + if (!str) { + KLOG_ERROR("Tried to copy null string"); + return 0; + } int len = kstrlen(str); char * new_str = kmalloc(len + 1); - kmemcpy(new_str, str, len + 1); + if (!new_str) { + KLOG_ERROR("Failed to malloc new string of length %d", len + 1); + return 0; + } + if (!kmemcpy(new_str, str, len + 1)) { + KLOG_ERROR("Failed to copy %u bytes in memory from %p to %p", len + 1, str, new_str); + return 0; + } return new_str; } static int copy_args(process_t * proc, const char * filepath, int argc, char ** argv) { - if (!proc || !filepath || !argv) { + if (!proc) { + KLOG_ERROR("Tried to copy args for null process"); + return -1; + } + if (!filepath) { + KLOG_ERROR("Missing filepath"); + return -1; + } + if (argc && !argv) { + KLOG_ERROR("Missing argv"); return -1; } proc->filepath = copy_string(filepath); - proc->argc = argc + 1; - proc->argv = kmalloc(sizeof(char *) * (argc + 1)); + if (!proc->filepath) { + KLOG_ERROR("Failed to copy filepath"); + return -1; + } + proc->argc = argc + 1; + proc->argv = kmalloc(sizeof(char *) * (argc + 1)); + if (!proc->argv) { + KLOG_ERROR("Failed to malloc process_t argv"); + kfree(proc->filepath); + return -1; + } - size_t len = kstrlen(filepath); proc->argv[0] = copy_string(filepath); + if (!proc->argv[0]) { + KLOG_ERROR("Failed to copy filepath to argv"); + kfree(proc->argv); + kfree(proc->filepath); + return -1; + } + for (int i = 0; i < argc; i++) { proc->argv[i + 1] = copy_string(argv[i]); + if (!proc->argv[i + 1]) { + KLOG_ERROR("Failed to copy arg %d", i); + for (int j = 0; j < i + 1; j++) { + kfree(proc->argv[i]); + } + kfree(proc->argv); + kfree(proc->filepath); + return -1; + } } return 0; diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 252e14a..4d4b0a1 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -109,24 +109,31 @@ static void setup_system_calls() { } int kernel_exec(const char * filename, size_t argc, char ** argv) { + if (!filename) { + KLOG_ERROR("Missing filename"); + return -1; + } tar_stat_t stat; if (!tar_stat_file(kernel_get_tar(), filename, &stat)) { - puts("Failed to find file\n"); + KLOG_ERROR("Failed to find file %s to execute", filename); return -1; } uint8_t * buff = kmalloc(stat.size); if (!buff) { + KLOG_ERROR("Failed to malloc buffer of size %u", stat.size); return -1; } tar_fs_file_t * file = tar_file_open(kernel_get_tar(), filename); if (!file) { + KLOG_ERROR("Failed to open file %s", filename); kfree(buff); return -1; } if (!tar_file_read(file, buff, stat.size)) { + KLOG_ERROR("Failed to read from file %s", filename); tar_file_close(file); kfree(buff); return -1; @@ -135,6 +142,7 @@ int kernel_exec(const char * filename, size_t argc, char ** argv) { int pid = command_exec(buff, filename, stat.size, argc, argv); if (pid < 0) { + KLOG_ERROR("Failed to execute file %s", filename); tar_file_close(file); kfree(buff); return -1; @@ -159,8 +167,13 @@ ebus_t * get_kernel_ebus() { } void kernel_queue_event(ebus_event_t * event) { - ebus_push(&__kernel.event_queue, event); - pm_push_event(&__kernel.pm, event); + if (ebus_push(&__kernel.event_queue, event)) { + KLOG_ERROR("Failed to push event to kernel event queue"); + return; + } + if (pm_push_event(&__kernel.pm, event)) { + KLOG_ERROR("Failed to push event to process manager"); + } } disk_t * kernel_get_disk() { diff --git a/src/kernel/src/kernel/panic.c b/src/kernel/src/kernel/panic.c index b6fb441..902aa07 100644 --- a/src/kernel/src/kernel/panic.c +++ b/src/kernel/src/kernel/panic.c @@ -1,5 +1,7 @@ +#include "kernel/panic.h" + #include "drivers/vga.h" -#include "kernel.h" +#include "kernel/logs.h" NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int line) { vga_color(VGA_FG_WHITE | VGA_BG_RED); @@ -15,6 +17,7 @@ NO_RETURN void kernel_panic(const char * msg, const char * file, unsigned int li vga_puts(msg); } vga_cursor_hide(); + KLOG_ERROR("[KERNEL PANIC][%s]:%u %s", file, line, msg); halt(); } diff --git a/src/kernel/src/loader.c b/src/kernel/src/loader.c index 4925ca8..11b4ebe 100644 --- a/src/kernel/src/loader.c +++ b/src/kernel/src/loader.c @@ -187,22 +187,69 @@ static void id_map_page(mmu_table_t * table, size_t page) { } static char * copy_string(const char * str) { + if (!str) { + KLOG_ERROR("Tried to copy null string"); + return 0; + } int len = kstrlen(str); char * new_str = kmalloc(len + 1); - kmemcpy(new_str, str, len + 1); + if (!new_str) { + KLOG_ERROR("Failed to malloc new string of length %d", len + 1); + return 0; + } + if (!kmemcpy(new_str, str, len + 1)) { + KLOG_ERROR("Failed to copy %u bytes in memory from %p to %p", len + 1, str, new_str); + return 0; + } return new_str; } -static int copy_args(process_t * proc, const char * filepath, int argc, const char ** argv) { - if (!proc || !filepath || !argv) { +static int copy_args(process_t * proc, const char * filepath, int argc, char ** argv) { + if (!proc) { + KLOG_ERROR("Tried to copy args for null process"); + return -1; + } + if (!filepath) { + KLOG_ERROR("Missing filepath"); + return -1; + } + if (argc && !argv) { + KLOG_ERROR("Missing argv"); return -1; } proc->filepath = copy_string(filepath); - proc->argc = argc; - proc->argv = kmalloc(sizeof(char *) * argc); + if (!proc->filepath) { + KLOG_ERROR("Failed to copy filepath"); + return -1; + } + proc->argc = argc + 1; + proc->argv = kmalloc(sizeof(char *) * (argc + 1)); + if (!proc->argv) { + KLOG_ERROR("Failed to malloc process_t argv"); + kfree(proc->filepath); + return -1; + } + + proc->argv[0] = copy_string(filepath); + if (!proc->argv[0]) { + KLOG_ERROR("Failed to copy filepath to argv"); + kfree(proc->argv); + kfree(proc->filepath); + return -1; + } + for (int i = 0; i < argc; i++) { - proc->argv[i] = copy_string(argv[i]); + proc->argv[i + 1] = copy_string(argv[i]); + if (!proc->argv[i + 1]) { + KLOG_ERROR("Failed to copy arg %d", i); + for (int j = 0; j < i + 1; j++) { + kfree(proc->argv[i]); + } + kfree(proc->argv); + kfree(proc->filepath); + return -1; + } } return 0; @@ -223,11 +270,12 @@ static void proc_entry() { } static process_t * load_init() { + // TODO use exec code or replace this with exec version of copy args const char * filename = "init"; tar_stat_t stat; if (!tar_stat_file(kernel_get_tar(), filename, &stat)) { - KLOGS_ERROR("init", "Failed to find file\n"); + KLOG_ERROR("Failed to find file\n"); return 0; } @@ -251,21 +299,24 @@ static process_t * load_init() { process_t * proc = kmalloc(sizeof(process_t)); if (process_create(proc)) { - KLOGS_ERROR("init", "Failed to create process\n"); + KLOG_ERROR("Failed to create process for %s", filename); return 0; } if (process_load_heap(proc, buff, stat.size)) { - KLOGS_ERROR("init", "Failed to load\n"); + KLOG_ERROR("Failed to load %s", filename); process_free(proc); return 0; } for (size_t i = 0; i < 1022; i++) { - process_grow_stack(proc); + if (process_grow_stack(proc)) { + KLOG_ERROR("Failed to grow process stack"); + return 0; + } } - copy_args(proc, filename, 1, &filename); + copy_args(proc, filename, 0, 0); process_set_entrypoint(proc, proc_entry); process_add_pages(proc, 32); diff --git a/src/kernel/src/paging.c b/src/kernel/src/paging.c index 830a8b6..b455584 100644 --- a/src/kernel/src/paging.c +++ b/src/kernel/src/paging.c @@ -1,8 +1,12 @@ #include "paging.h" #include "drivers/ram.h" +#include "kernel/logs.h" #include "libc/string.h" +#undef SERVICE +#define SERVICE "KERNEL/PAGING" + typedef struct { uint32_t addr; size_t count; @@ -10,15 +14,28 @@ typedef struct { static page_user_t __temp_pages[VADDR_TMP_PAGE_COUNT]; -void paging_init() { - kmemset(__temp_pages, 0, sizeof(__temp_pages)); +int paging_init() { + if (!kmemset(__temp_pages, 0, sizeof(__temp_pages))) { + KLOG_ERROR("Failed to clear temp pages array"); + return -1; + } + + KLOG_DEBUG("Paging initialized"); + return 0; } void * paging_temp_map(uint32_t paddr) { - if (!paddr || paddr & MASK_FLAGS) { + if (!paddr) { + KLOG_ERROR("Trying to map physical address 0"); + return 0; + } + if (paddr & MASK_FLAGS) { + KLOG_ERROR("Trying to map misaligned physical address %p", paddr); return 0; } + KLOG_TRACE("Map temporary page for physical address %p", paddr); + // Return one if already exists for (size_t i = 0; i < VADDR_TMP_PAGE_COUNT; i++) { if (__temp_pages[i].addr == paddr) { @@ -38,7 +55,13 @@ void * paging_temp_map(uint32_t paddr) { mmu_table_t * table = (mmu_table_t *)VADDR_KERNEL_TABLE; uint32_t vaddr = PAGE2ADDR(table_i); - mmu_table_set(table, table_i, paddr, MMU_TABLE_RW); + + KLOG_TRACE("Mapping physical address %p to table index %u virtual address %p", paddr, table_i, vaddr); + + if (mmu_table_set(table, table_i, paddr, MMU_TABLE_RW)) { + KLOG_ERROR("Failed to set mmu table index %u to physical address %p", table_i, paddr); + return 0; + } mmu_flush_tlb(vaddr); return UINT2PTR(vaddr); } @@ -47,22 +70,37 @@ void * paging_temp_map(uint32_t paddr) { return 0; } -void paging_temp_free(uint32_t paddr) { - if (!paddr || paddr & MASK_FLAGS) { - return; +int paging_temp_free(uint32_t paddr) { + if (!paddr) { + KLOG_ERROR("Trying to free physical address 0"); + return -1; } + if (paddr & MASK_FLAGS) { + KLOG_ERROR("Trying to free misaligned physical address %p", paddr); + return -1; + } + + KLOG_TRACE("Free temporary page for physical address %p", paddr); for (size_t i = 0; i < VADDR_TMP_PAGE_COUNT; i++) { if (__temp_pages[i].addr == paddr) { - if (__temp_pages[i].count < 1) { - return; + if (!__temp_pages[i].count) { + KLOG_ERROR("Trying to free temp page %u which has count 0", i); + return -1; } __temp_pages[i].count--; - break; + uint32_t vaddr = PAGE2ADDR(i); + KLOG_TRACE("Freed temporary page %u with virtual address %p from physical address %p", i, vaddr, paddr); + + return 0; } } + + KLOG_ERROR("Failed to find mapping for physical address %u", paddr); + + return -1; } size_t paging_temp_available() { @@ -78,8 +116,14 @@ size_t paging_temp_available() { } int paging_id_map_range(size_t start, size_t end) { + if (start > end) { + KLOG_WARNING("Trying to map range with start %u after end %u", start, end); + return -1; + } + while (start <= end) { if (paging_id_map_page(start++)) { + // Error logged in paging_id_map_page return -1; } } @@ -89,6 +133,7 @@ int paging_id_map_range(size_t start, size_t end) { int paging_id_map_page(size_t page) { if (page >= MMU_TABLE_SIZE) { + KLOG_ERROR("Failed to identity map page %u", page); return -1; } @@ -100,16 +145,18 @@ int paging_id_map_page(size_t page) { int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { if (!dir) { + KLOG_ERROR("Trying to add page to null directory"); return -1; } - if (start > end) { - return 0; + KLOG_WARNING("Trying to add pages for range with start %u after end %u", start, end); + return -1; } uint32_t table_end = end / MMU_TABLE_SIZE; if (table_end >= MMU_DIR_SIZE) { + KLOG_WARNING("End %u is after last table end %u", end, MMU_DIR_SIZE * MMU_TABLE_SIZE); return -1; } @@ -118,7 +165,9 @@ int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { uint32_t addr = ram_page_alloc(); if (!addr) { - paging_remove_pages(dir, start, page_i - 1); + if (paging_remove_pages(dir, start, page_i - 1)) { + KLOG_ERROR("Failed to remove page from directory"); + } return -1; } @@ -128,8 +177,12 @@ int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { // Add table if needed if (!(mmu_dir_get_flags(dir, dir_i) & MMU_DIR_FLAG_PRESENT)) { if (paging_add_table(dir, dir_i)) { - paging_remove_pages(dir, start, page_i - 1); - ram_page_free(addr); + if (paging_remove_pages(dir, start, page_i - 1)) { + KLOG_ERROR("Failed to remove page from directory %p", dir); + } + if (ram_page_free(addr)) { + KLOG_ERROR("Failed to free ram page"); + } return -1; } } @@ -139,14 +192,25 @@ int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { mmu_table_t * table = paging_temp_map(table_addr); if (!table) { - paging_remove_pages(dir, start, page_i - 1); - paging_temp_free(table_addr); - ram_page_free(addr); + KLOG_ERROR("Failed to create temporary map for %p", table_addr); + if (paging_remove_pages(dir, start, page_i - 1)) { + KLOG_ERROR("Failed to remove page from directory %p", dir); + } + if (ram_page_free(addr)) { + KLOG_ERROR("Failed to free ram page"); + } return -1; } - mmu_table_set(table, table_i, addr, MMU_TABLE_RW); - paging_temp_free(table_addr); + // TODO should either be panic or log error and return? + if (mmu_table_set(table, table_i, addr, MMU_TABLE_RW)) { + KLOG_ERROR("Failed to set page table %p index %u to physical address %p", table, table_i, addr); + return -1; + } + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary page"); + return -1; + } } return 0; @@ -154,16 +218,18 @@ int paging_add_pages(mmu_dir_t * dir, size_t start, size_t end) { int paging_remove_pages(mmu_dir_t * dir, size_t start, size_t end) { if (!dir) { + KLOG_ERROR("Trying to remove page from null directory"); return -1; } - if (start > end) { - return 0; + KLOG_WARNING("Trying to remove pages for range with start %u after end %u", start, end); + return -1; } uint32_t table_end = end / MMU_TABLE_SIZE; if (table_end >= MMU_DIR_SIZE) { + KLOG_WARNING("End %u is after last table end %u", end, MMU_TABLE_SIZE); return -1; } @@ -182,6 +248,7 @@ int paging_remove_pages(mmu_dir_t * dir, size_t start, size_t end) { mmu_table_t * table = paging_temp_map(table_addr); if (!table) { + KLOG_ERROR("Failed to create temporary map for %p", table_addr); return -1; } @@ -192,17 +259,32 @@ int paging_remove_pages(mmu_dir_t * dir, size_t start, size_t end) { uint32_t page_addr = mmu_table_get_addr(table, table_i); - mmu_table_set(table, table_i, 0, 0); + // TODO should either be panic or log error and return? + if (mmu_table_set(table, table_i, 0, 0)) { + KLOG_ERROR("Failed to clear page table %p index %u", table, table_i); + return -1; + } mmu_flush_tlb(PAGE2ADDR(page_i)); - ram_page_free(page_addr); - paging_temp_free(table_addr); + if (ram_page_free(page_addr)) { + KLOG_ERROR("Failed to free ram page"); + return -1; + } + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary mapping for table %p", table_addr); + return -1; + } } return 0; } int paging_add_table(mmu_dir_t * dir, size_t dir_i) { - if (!dir || dir_i >= MMU_DIR_SIZE) { + if (!dir) { + KLOG_ERROR("Trying to add table to null directory"); + return -1; + } + if (dir_i >= MMU_DIR_SIZE) { + KLOG_ERROR("Directory index %u is past directory end %p", dir_i, MMU_DIR_SIZE); return -1; } @@ -216,12 +298,20 @@ int paging_add_table(mmu_dir_t * dir, size_t dir_i) { mmu_table_t * table = paging_temp_map(addr); if (!table) { - ram_page_free(addr); + if (ram_page_free(addr)) { + KLOG_ERROR("Failed to free ram page"); + } return -1; } mmu_table_clear(table); - mmu_dir_set(dir, dir_i, addr, MMU_DIR_RW); + if (mmu_dir_set(dir, dir_i, addr, MMU_DIR_RW)) { + KLOG_ERROR("Failed to set page directory %p index %u to physical address %p", dir, dir_i, addr); + if (paging_temp_free(addr)) { + KLOG_ERROR("Failed to free temporary page"); + } + return -1; + } paging_temp_free(addr); } @@ -230,14 +320,28 @@ int paging_add_table(mmu_dir_t * dir, size_t dir_i) { } int paging_remove_table(mmu_dir_t * dir, size_t dir_i) { - if (!dir || dir_i >= MMU_DIR_SIZE) { + if (!dir) { + KLOG_ERROR("Trying to remove table from null directory"); + return -1; + } + if (dir_i >= MMU_DIR_SIZE) { + KLOG_ERROR("Directory index %u is past directory end %p", dir_i, MMU_DIR_SIZE); return -1; } if (mmu_dir_get_flags(dir, dir_i) & MMU_DIR_FLAG_PRESENT) { uint32_t addr = mmu_dir_get_addr(dir, dir_i); - mmu_dir_set(dir, dir_i, 0, 0); - ram_page_free(addr); + if (!addr) { + KLOG_ERROR("Failed to get address of table %u from directory %p", dir_i, dir); + return -1; + } + if (mmu_dir_set(dir, dir_i, 0, 0)) { + KLOG_ERROR("Failed to clear table %u from directory %p", dir_i, dir); + return -1; + } + if (ram_page_free(addr)) { + KLOG_ERROR("Failed to free ram page"); + } } return 0; diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 1f9fe9d..718b231 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -11,6 +11,9 @@ #include "libk/sys_call.h" #include "paging.h" +#undef SERVICE +#define SERVICE "KERNEL/PROCESS" + static int open_stdio_handles(process_t * proc); static uint32_t next_pid(); @@ -18,14 +21,19 @@ static uint32_t next_handle_id(); int process_create(process_t * proc) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); return -1; } - kmemset(proc, 0, sizeof(process_t)); + if (!kmemset(proc, 0, sizeof(process_t))) { + KLOG_ERROR("Failed to clear process struct"); + return -1; + } proc->cr3 = ram_page_alloc(); if (!proc->cr3) { + KLOG_ERROR("Failed to allocate ram page for process page directory"); return -1; } @@ -33,21 +41,33 @@ int process_create(process_t * proc) { mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { - ram_page_free(proc->cr3); + KLOG_ERROR("Failed to create temporary mapping for physical address %p", proc->cr3); + if (ram_page_free(proc->cr3)) { + KLOG_ERROR("Failed to free ram page %p for process page directory", proc->cr3); + } return -1; } uint32_t kernel_table_addr = mmu_dir_get_addr((mmu_dir_t *)VADDR_KERNEL_DIR, 0); + if (!kernel_table_addr) { + KLOG_ERROR("Failed to get physical address of kernel table"); + return -1; + } // Copy first page table from kernel page directory mmu_dir_clear(dir); - mmu_dir_set(dir, 0, kernel_table_addr, MMU_DIR_RW); + if (mmu_dir_set(dir, 0, kernel_table_addr, MMU_DIR_RW)) { + KLOG_ERROR("Failed to set kernel table address in process page directory %p", dir); + return -1; + } proc->esp = VADDR_USER_STACK; proc->esp0 = VADDR_ISR_STACK; // Allocate pages for ISR stack + first page of user stack if (paging_add_pages(dir, ADDR2PAGE(proc->esp), ADDR2PAGE(proc->esp0))) { + KLOG_ERROR("Failed to create pages for isr and user stacks"); + // Error logged in function, not logging here because we are already returning error paging_temp_free(proc->cr3); ram_page_free(proc->cr3); return -1; @@ -57,20 +77,27 @@ int process_create(process_t * proc) { proc->next_heap_page = ADDR2PAGE(VADDR_USER_MEM); proc->stack_page_count = 1; - paging_temp_free(proc->cr3); + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary page"); + ram_page_free(proc->cr3); + return -1; + } if (arr_create(&proc->io_handles, 4, sizeof(handle_t))) { + KLOG_ERROR("Failed to create array for io handles"); ram_page_free(proc->cr3); return -1; } if (ebus_create(&proc->event_queue, 4096)) { + KLOG_ERROR("Failed to create ebus for process event queue"); arr_free(&proc->io_handles); ram_page_free(proc->cr3); return -1; } if (memory_init(&proc->memory, kernel_alloc_page)) { + KLOG_ERROR("Failed to initialize malloc for process"); ebus_free(&proc->event_queue); arr_free(&proc->io_handles); ram_page_free(proc->cr3); @@ -79,6 +106,7 @@ int process_create(process_t * proc) { proc->io_buffer = io_buffer_create(IO_BUFFER_SIZE); if (!proc->io_buffer) { + KLOG_ERROR("Failed to create io buffer"); ebus_free(&proc->event_queue); arr_free(&proc->io_handles); ram_page_free(proc->cr3); @@ -86,6 +114,7 @@ int process_create(process_t * proc) { } if (open_stdio_handles(proc)) { + KLOG_ERROR("Failed to open stdio handles"); ebus_free(&proc->event_queue); arr_free(&proc->io_handles); ram_page_free(proc->cr3); @@ -98,6 +127,7 @@ int process_create(process_t * proc) { int process_free(process_t * proc) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); return -1; } @@ -107,6 +137,7 @@ int process_free(process_t * proc) { mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to create temporary mapping for process pageing directory"); return -1; } @@ -120,6 +151,7 @@ int process_free(process_t * proc) { mmu_table_t * table = paging_temp_map(table_addr); if (!table) { + KLOG_ERROR("Failed to create temporary mapping for process page table"); paging_temp_free(proc->cr3); ram_page_free(proc->cr3); return -1; @@ -133,19 +165,40 @@ int process_free(process_t * proc) { } } - paging_temp_free(table_addr); - ram_page_free(table_addr); + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary map of process page table"); + return -1; + } + if (ram_page_free(table_addr)) { + KLOG_ERROR("Failed to free ram page for process page table"); + return -1; + } } // Free dir - paging_temp_free(proc->cr3); - ram_page_free(proc->cr3); + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary map of process page directory"); + return -1; + } + if (ram_page_free(proc->cr3)) { + KLOG_ERROR("Failed to free ram page for process page directory"); + return -1; + } return 0; } int process_set_entrypoint(process_t * proc, void * entrypoint) { - if (!proc || !entrypoint || proc->state >= PROCESS_STATE_SUSPENDED) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!entrypoint) { + KLOG_ERROR("Entrypoint is null pointer"); + return -1; + } + if (proc->state >= PROCESS_STATE_SUSPENDED) { + KLOG_ERROR("Process already started"); return -1; } @@ -157,23 +210,37 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to create temporary map for process page directory"); return -1; } uint32_t table_addr = mmu_dir_get_addr(dir, dir_i); + if (!table_addr) { + KLOG_ERROR("Failed to get physical address of process page directory"); + paging_temp_free(proc->cr3); + return -1; + } mmu_table_t * table = paging_temp_map(table_addr); if (!table) { + KLOG_ERROR("Failed to create temporary map for process page table"); paging_temp_free(proc->cr3); return -1; } uint32_t page_addr = mmu_table_get_addr(table, table_i); + if (!table_addr) { + KLOG_ERROR("Failed to get physical address of process page"); + paging_temp_free(table_addr); + paging_temp_free(proc->cr3); + return -1; + } uint32_t * stack = paging_temp_map(page_addr); if (!stack) { + KLOG_ERROR("Failed to create temporary map for process stack page"); paging_temp_free(table_addr); paging_temp_free(proc->cr3); return -1; @@ -182,9 +249,18 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { int ret_i = (proc->esp % PAGE_SIZE) / 4; stack[ret_i] = PTR2UINT(entrypoint); - paging_temp_free(page_addr); - paging_temp_free(table_addr); - paging_temp_free(proc->cr3); + if (paging_temp_free(page_addr)) { + KLOG_ERROR("Failed to free temporary map for process stack page"); + return -1; + } + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary map for process page table"); + return -1; + } + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary map for process page directory"); + return -1; + } proc->esp -= (5 * 4) - 1; @@ -192,7 +268,16 @@ int process_set_entrypoint(process_t * proc, void * entrypoint) { } int process_resume(process_t * proc, const ebus_event_t * event) { - if (!proc || proc->state < PROCESS_STATE_LOADED || proc->state >= PROCESS_STATE_DEAD) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (proc->state < PROCESS_STATE_LOADED) { + KLOG_ERROR("Process not yet started"); + return -1; + } + if (proc->state >= PROCESS_STATE_DEAD) { + KLOG_ERROR("Process is dead"); return -1; } @@ -202,7 +287,11 @@ int process_resume(process_t * proc, const ebus_event_t * event) { } active_before->state = PROCESS_STATE_SUSPENDED; + KLOG_TRACE("Setting process state for pid %u to SUSPENDED", active_before->pid); + proc->state = PROCESS_STATE_RUNNING; + KLOG_TRACE("Setting process state for pid %u to RUNNING", proc->pid); + switch_task(proc); // Call this again because we are a new process now @@ -213,26 +302,37 @@ int process_resume(process_t * proc, const ebus_event_t * event) { } void * process_add_pages(process_t * proc, size_t count) { - if (!proc || !count) { + if (!proc) { + KLOG_ERROR("Tried to add page to null process"); + return 0; + } + if (!count) { + KLOG_WARNING("Add page count is 0"); return 0; } if (proc->next_heap_page + count >= MMU_DIR_SIZE * MMU_TABLE_SIZE) { + KLOG_ERROR("Cannot allocate %u pages after %u, will exceed max size of %d", count, proc->next_heap_page, MMU_DIR_SIZE * MMU_TABLE_SIZE); return 0; } mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to map a temporary page for pid %u page dir", proc->pid); return 0; } if (paging_add_pages(dir, proc->next_heap_page, proc->next_heap_page + count)) { + KLOG_ERROR("Failed to add %u pages to pid %u", count, proc->pid); paging_temp_free(proc->cr3); return 0; } - paging_temp_free(proc->cr3); + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary page for process page directory"); + return 0; + } void * ptr = UINT2PTR(PAGE2ADDR(proc->next_heap_page)); proc->next_heap_page += count; @@ -242,38 +342,55 @@ void * process_add_pages(process_t * proc, size_t count) { int process_grow_stack(process_t * proc) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); return -1; } mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to create temporary map of process page directory"); return -1; } size_t new_stack_page_i = MMU_DIR_SIZE * MMU_TABLE_SIZE - proc->stack_page_count - 1; if (paging_add_pages(dir, new_stack_page_i, new_stack_page_i)) { + KLOG_ERROR("Failed to add pages fo process stack"); paging_temp_free(proc->cr3); return -1; } - proc->stack_page_count--; + proc->stack_page_count++; - paging_temp_free(proc->cr3); + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary map of process page dir"); + return -1; + } return 0; } int process_load_heap(process_t * proc, const char * buff, size_t size) { - if (!proc || !buff || !size) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!buff) { + KLOG_ERROR("Trying to load heap from null buffer"); + return -1; + } + if (!size) { + KLOG_ERROR("Trying to load empty buffer"); return -1; } + KLOG_TRACE("Setting process pid %u state to LOADING", proc->pid); proc->state = PROCESS_STATE_LOADING; size_t page_count = ADDR2PAGE(size); if (size & MASK_FLAGS) { + KLOG_TRACE("Increasing page count by 1 to align with page boundary"); page_count++; } @@ -281,28 +398,43 @@ int process_load_heap(process_t * proc, const char * buff, size_t size) { void * heap_alloc = process_add_pages(proc, page_count); if (!heap_alloc) { + KLOG_ERROR("Failed to allocate pages for process pid %u heap", proc->pid); return -1; } mmu_dir_t * dir = paging_temp_map(proc->cr3); if (!dir) { + KLOG_ERROR("Failed to create temporary mapping of process page directory"); return -1; } for (size_t i = 0; i < page_count; i++) { - uint32_t table_addr = mmu_dir_get_addr(dir, (heap_start + i) / MMU_TABLE_SIZE); - mmu_table_t * table = paging_temp_map(table_addr); + uint32_t table_addr = mmu_dir_get_addr(dir, (heap_start + i) / MMU_TABLE_SIZE); + if (!table_addr) { + KLOG_ERROR("Failed to get physical address of process pid %u page table", proc->pid); + paging_temp_free(proc->cr3); + return -1; + } + mmu_table_t * table = paging_temp_map(table_addr); if (!table) { + KLOG_ERROR("Failed to create temporary mapping of process pid %u page table %p", proc->pid, table_addr); paging_temp_free(proc->cr3); return -1; } - uint32_t addr = mmu_table_get_addr(table, (heap_start + i) % MMU_TABLE_SIZE); - void * tmp_page = paging_temp_map(addr); + uint32_t addr = mmu_table_get_addr(table, (heap_start + i) % MMU_TABLE_SIZE); + if (!table_addr) { + KLOG_ERROR("Failed to get physical address of process pid %u page table", proc->pid); + paging_temp_free(table_addr); + paging_temp_free(proc->cr3); + return -1; + } + void * tmp_page = paging_temp_map(addr); if (!tmp_page) { + KLOG_ERROR("Failed to create temporary map of process pid %u page %p", proc->pid, addr); paging_temp_free(table_addr); paging_temp_free(proc->cr3); return -1; @@ -316,19 +448,34 @@ int process_load_heap(process_t * proc, const char * buff, size_t size) { kmemcpy(tmp_page, &buff[i * PAGE_SIZE], to_copy); - paging_temp_free(addr); - paging_temp_free(table_addr); + if (paging_temp_free(addr)) { + KLOG_ERROR("Failed to free temporary map of process pid %u page"); + return -1; + } + if (paging_temp_free(table_addr)) { + KLOG_ERROR("Failed to free temporary map of process pid %u page table"); + return -1; + } } - paging_temp_free(proc->cr3); + if (paging_temp_free(proc->cr3)) { + KLOG_ERROR("Failed to free temporary map of process pid %u page directory"); + return -1; + } + KLOG_TRACE("Setting process pid %u state to LOADED", proc->pid); proc->state = PROCESS_STATE_LOADED; return 0; } handle_t * process_get_handle(process_t * proc, int id) { - if (!proc || id < 0) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return 0; + } + if (id < 0) { + KLOG_ERROR("id must be >= 0, got %d", id); return 0; } @@ -340,11 +487,18 @@ handle_t * process_get_handle(process_t * proc, int id) { } } + KLOG_ERROR("Failed to find handle %d for process pid %u", id, proc->pid); + return 0; } int process_add_handle(process_t * proc, int id, int flags, io_device_t * device) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!device) { + KLOG_ERROR("Devices is a null pointer"); return -1; } @@ -359,7 +513,7 @@ int process_add_handle(process_t * proc, int id, int flags, io_device_t * device }; if (arr_insert(&proc->io_handles, arr_size(&proc->io_handles), &h)) { - KLOGS_ERROR("process", "Could not add new handle to process"); + KLOG_ERROR("Could not add new handle to process"); return -1; } @@ -368,6 +522,7 @@ int process_add_handle(process_t * proc, int id, int flags, io_device_t * device static int open_stdio_handles(process_t * proc) { if (!proc) { + KLOG_ERROR("Process struct is null pointer"); return -1; } @@ -375,14 +530,14 @@ static int open_stdio_handles(process_t * proc) { // process_add_handle returns handle id if (process_add_handle(proc, 1, DEVICE_IO_FLAG_WRITE, device_screen_open()) < 0) { - KLOGS_ERROR("process", "Failed to create stdout handle"); + KLOG_ERROR("Failed to create stdout handle"); return -1; } handle_t * h = arr_at(&proc->io_handles, 0); if (process_add_handle(proc, 2, DEVICE_IO_FLAG_WRITE, device_screen_open()) < 0) { - KLOGS_ERROR("process", "Failed to create stderr handle"); + KLOG_ERROR("Failed to create stderr handle"); return -1; } diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 0d4c114..0c55065 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -7,16 +7,24 @@ #include "libc/stdio.h" #include "libc/string.h" +#undef SERVICE +#define SERVICE "KERNEL/PROCESS_MANAGER" + static int pid_arr_index(arr_t * arr, int pid); int pm_create(proc_man_t * pm) { if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); return -1; } - kmemset(pm, 0, sizeof(proc_man_t)); + if (!kmemset(pm, 0, sizeof(proc_man_t))) { + KLOG_ERROR("Failed to clear process manager struct"); + return -1; + } if (arr_create(&pm->task_list, 4, sizeof(process_t *))) { + KLOG_ERROR("Failed to create process manager task list array"); return -1; } @@ -24,27 +32,43 @@ int pm_create(proc_man_t * pm) { } process_t * pm_find_pid(proc_man_t * pm, int pid) { - if (!pm || pid < 0) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); + return 0; + } + if (pid < 0) { + KLOG_WARNING("Find takes a pid >= 0, got %d", pid); return 0; } int i = pid_arr_index(&pm->task_list, pid); if (i < 0) { + // TODO should this be warning or debug / trace? + KLOG_WARNING("Failed to find process pid %d", pid); return 0; } process_t * proc; - arr_get(&pm->task_list, i, &proc); + if (arr_get(&pm->task_list, i, &proc)) { + KLOG_ERROR("Failed to get process for index %d", i); + return 0; + } return proc; } int pm_add_proc(proc_man_t * pm, process_t * proc) { - if (!pm || !proc) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); + return -1; + } + if (!proc) { + KLOG_ERROR("Process struct is a null pointer"); return -1; } if (arr_insert(&pm->task_list, arr_size(&pm->task_list), &proc)) { + KLOG_ERROR("Failed to insert process pid %u into process manager", proc->pid); return -1; } @@ -52,44 +76,64 @@ int pm_add_proc(proc_man_t * pm, process_t * proc) { } int pm_remove_proc(proc_man_t * pm, int pid) { - if (!pm || pid < 0) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); + return -1; + } + if (pid < 0) { + KLOG_WARNING("Remove process takes a pid >= 0, got %d", pid); return -1; } if (pid == get_active_task()->pid) { + KLOG_ERROR("Trying to remove active task pid %d", pid); return -1; } int i = pid_arr_index(&pm->task_list, pid); if (i < 0 || arr_remove(&pm->task_list, i, 0)) { + KLOG_ERROR("Failed to remove process from task list array"); return -1; } - return -1; + return 0; } int pm_set_foreground_proc(proc_man_t * pm, int pid) { - if (!pm || pid < 0) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); + return -1; + } + if (pid < 0) { + KLOG_WARNING("Set foreground process takes a pid >= 0, got %d", pid); return -1; } process_t * proc = pm_find_pid(pm, pid); if (!proc) { + KLOG_ERROR("Failed to find process for pid %d", pid); return -1; } pm->foreground_task = proc; - return -1; + return 0; } int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); + return -1; + } + if (pid < 0) { + KLOG_WARNING("Set foreground process takes a pid >= 0, got %d", pid); return -1; } + // TODO event is not used process_t * proc = pm_find_pid(pm, pid); if (!proc) { + KLOG_ERROR("Failed to find process for pid %d", pid); return -1; } @@ -98,11 +142,13 @@ int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { process_t * pm_get_next(proc_man_t * pm) { if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); return 0; } int i = pid_arr_index(&pm->task_list, get_active_task()->pid); if (i < 0) { + KLOG_ERROR("Failed to fin index of current task"); return 0; } @@ -119,12 +165,12 @@ process_t * pm_get_next(proc_man_t * pm) { return 0; } - KLOGS_TRACE("pm", "PID %u is state %x", proc->pid, proc->state); + KLOG_TRACE("PID %u is state %x", proc->pid, proc->state); // if (proc->state == PROCESS_STATE_WAITING_STDIN) { - // KLOGS_DEBUG("pm", "Process waiting for stdin"); + // KLOG_DEBUG("Process waiting for stdin"); // if (io_buffer_length(proc->io_buffer) > 0) { - // KLOGS_DEBUG("pm", "Process is waiting for stdin and has %u ready", io_buffer_length(proc->io_buffer)); + // KLOG_DEBUG("Process is waiting for stdin and has %u ready", io_buffer_length(proc->io_buffer)); // return proc; // } // } @@ -155,6 +201,11 @@ process_t * pm_get_next(proc_man_t * pm) { static int pid_arr_index(arr_t * arr, int pid) { if (!arr) { + KLOG_ERROR("Array is a null pointer"); + return -1; + } + if (pid < 0) { + KLOG_WARNING("PID array find index takes a pid >= 0, got %d", pid); return -1; } @@ -167,28 +218,36 @@ static int pid_arr_index(arr_t * arr, int pid) { } } + KLOG_ERROR("Failed to find index of pid %u", pid); + return -1; } int pm_push_event(proc_man_t * pm, ebus_event_t * event) { - if (!pm || !event) { + if (!pm) { + KLOG_ERROR("Process manager struct is a null pointer"); + return -1; + } + if (!event) { + KLOG_ERROR("Event is a null pointer"); return -1; } if (event->event_id = EBUS_EVENT_KEY) { process_t * foreground = pm->foreground_task; - KLOGS_TRACE("pm", "Foreground is %u", foreground->pid); + KLOG_TRACE("Foreground is %u", foreground->pid); // if (event->key.event == KEY_EVENT_PRESS) { // if (io_buffer_push(foreground->io_buffer, event->key.c)) { - // KLOGS_WARNING("pm", "Failed to push key into io buffer"); + // KLOG_WARNING("Failed to push key into io buffer"); // return -1; // } - // KLOGS_TRACE("pm", "IO buffer is size %u", io_buffer_length(foreground->io_buffer)); + // KLOG_TRACE("IO buffer is size %u", io_buffer_length(foreground->io_buffer)); // } if (ebus_push(&foreground->event_queue, event)) { + KLOG_ERROR("Failed to push event to ebus for foreground process"); return -1; } } @@ -208,8 +267,9 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { } if (proc->filter_event == event->event_id) { - KLOGS_DEBUG("pm", "Process %u was waiting for %u and got it", proc->pid, proc->filter_event); + KLOG_DEBUG("Process %u was waiting for %u and got it", proc->pid, proc->filter_event); if (ebus_push(&proc->event_queue, event)) { + KLOG_ERROR("Failed to push event to ebus for process %u", proc->pid); return -1; } @@ -219,5 +279,6 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { } } } + return 0; } diff --git a/tests/src/mocks/include/paging.mock.h b/tests/src/mocks/include/paging.mock.h index 6c65b3e..6ac36b8 100644 --- a/tests/src/mocks/include/paging.mock.h +++ b/tests/src/mocks/include/paging.mock.h @@ -8,9 +8,9 @@ extern "C" { #include "fff.h" #include "paging.h" -DECLARE_FAKE_VOID_FUNC(paging_init); +DECLARE_FAKE_VALUE_FUNC(int, paging_init); DECLARE_FAKE_VALUE_FUNC(void *, paging_temp_map, uint32_t); -DECLARE_FAKE_VOID_FUNC(paging_temp_free, uint32_t); +DECLARE_FAKE_VALUE_FUNC(int, paging_temp_free, uint32_t); DECLARE_FAKE_VALUE_FUNC(size_t, paging_temp_available); DECLARE_FAKE_VALUE_FUNC(int, paging_id_map_range, size_t, size_t); DECLARE_FAKE_VALUE_FUNC(int, paging_id_map_page, size_t); diff --git a/tests/src/mocks/src/paging.mock.c b/tests/src/mocks/src/paging.mock.c index fa9a776..33ba921 100644 --- a/tests/src/mocks/src/paging.mock.c +++ b/tests/src/mocks/src/paging.mock.c @@ -1,9 +1,9 @@ #include "paging.mock.h" -DEFINE_FAKE_VOID_FUNC(paging_init); +DEFINE_FAKE_VALUE_FUNC(int, paging_init); DEFINE_FAKE_VALUE_FUNC(void *, paging_temp_map, uint32_t); -DEFINE_FAKE_VOID_FUNC(paging_temp_free, uint32_t); +DEFINE_FAKE_VALUE_FUNC(int, paging_temp_free, uint32_t); DEFINE_FAKE_VALUE_FUNC(size_t, paging_temp_available); DEFINE_FAKE_VALUE_FUNC(int, paging_id_map_range, size_t, size_t); DEFINE_FAKE_VALUE_FUNC(int, paging_id_map_page, size_t); From 28953eb52bb5331346fb0a9512cb325bd8bda535 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 06:42:50 -0500 Subject: [PATCH 04/38] Replace uint16_t int_no with uint32_t call_id --- design/system_call.md | 123 ++++++++++++++----- src/kernel/include/kernel/system_call_io.h | 2 +- src/kernel/include/kernel/system_call_mem.h | 2 +- src/kernel/include/kernel/system_call_proc.h | 2 +- src/kernel/include/system_call.h | 4 +- src/kernel/src/drivers/vga.c | 4 +- src/kernel/src/kernel.c | 6 +- src/kernel/src/kernel/system_call_io.c | 18 +-- src/kernel/src/kernel/system_call_mem.c | 14 +-- src/kernel/src/kernel/system_call_proc.c | 26 ++-- src/kernel/src/kernel/time.c | 1 + src/kernel/src/system_call.c | 14 ++- src/libk/include/libk/defs.h | 89 +++++++------- src/libk/src/sys_call.c | 38 +++--- 14 files changed, 207 insertions(+), 136 deletions(-) diff --git a/design/system_call.md b/design/system_call.md index 89ff811..b02eafd 100644 --- a/design/system_call.md +++ b/design/system_call.md @@ -1,14 +1,77 @@ # WIP - System Calls +- [x] How system calls are defined (int no.) +- [x] How system calls are sent (wrapper) +- [ ] How system calls are receive (callback) +- [ ] System call wrapper +- [ ] Receiving args +- [ ] Returning value +- [ ] When virtual memory changes, args are invalid? Or not because it's the kernel stack + +## Sending System Calls + +System calls are sent to the kernel through interrupt 48 (`int 0x30`) which is +sent to IRQ 16. Each system call has a wrapper function in libk which calls one +of two functions, `send_call` or `send_call_noret`. These functions take a +`uint32_t` call id followed by some number va args. + +```c +extern int send_call(uint32_t int_no, ...); +extern NO_RETURN void send_call_noret(uint32_t int_no, ...); +``` + +> [!TIP] +> Wrapper functions are declared in +> [src/libk/include/libk/sys_call.h](../src/libk/include/libk/sys_call.h) and +> defined in [src/libk/src/sys_call.c](../src/libk/src/sys_call.c). + +### Call Id + +The system call id is a `uint32_t` where the first 16 bits are the family +followed by 16 bits for the call number. + +| Family | Call | +| ------- | ------- | +| 16 bits | 16 bits | + +> [!TIP] +> System call ids are defined in +> [src/libk/include/libk/defs.h](../src/libk/include/libk/defs.h). + +## Receiving System Calls + +- handled by callback +- registered using system_call_register + +# OLD + System calls are performed through interrupt 48 (`int 0x30`). The interrupt -takes a `uint16_t` id and some number of arguments. +takes a `uint32_t` id and some number of arguments. -Each interrupt takes up to 3 arguments and returns a `uint32_t`. +Each system call is defined by a function in libk which wraps the `send_call` +and `send_call_noret` functions. + +```c +extern int send_call(uint32_t int_no, ...); +extern NO_RETURN void send_call_noret(uint32_t int_no, ...); +``` + + + +TODO - max 256 callbacks per family, family is a 24 bit number +TODO - register callbacks +TODO - callback signature +TODO - accessing args in callback +TODO - args not available after page swap, need to copy anything not on the stack into kernel memory ## System Calls These are calls from the process to the kernel +> [!WARNING] This section is out of date +> See [src/libk/include/libk/defs.h](../src/libk/include/libk/defs.h) for the +> current implementation. + | ID | Family | | ---- | --------------- | | 0x01 | I/O | @@ -20,34 +83,34 @@ An interrupt id is an 8 bit family + an 8 bit id. | Family | ID | Name | | --------------- | ------ | ------------------------------------------------------------------------- | -| I/O | 0x0100 | open | -| | 0x0101 | close | -| | 0x0102 | read | -| | 0x0103 | write | -| | 0x0104 | seek | -| | 0x0105 | tell | -| Memory | 0x0200 | `void * malloc(size_t size)` | -| | 0x0201 | `void * realloc(void * ptr, size_t size)` | -| | 0x0202 | `void free(void * ptr)` | -| Process Control | 0x0300 | `void exit(uint8_t code)` | -| | 0x0301 | `void abort(uint8_t code, const char * msg)` | -| | 0x0302 | `void panic(const char * msg, const char * file, unsigned int line)` | -| | 0x0303 | `int register_signals(void * callback)` | -| | 0x0304 | `int getpid()` | -| Tmp Std I/O | 0x1000 | `size_t putc(char c)` | -| | 0x1001 | `size_t puts(const char * str)` | -| | 0x1002 | `size_t vprintf(const char * fmt, va_list params)` | -| File I/O | 0x1101 | `file_t file_open(const char * path, const char * mode)` | -| | 0x1102 | `void file_close(file_t)` | -| | 0x1103 | `size_t file_read(file_t, size_t size, size_t count, void * buff)` | -| | 0x1104 | `size_t file_write(file_t, size_t size, size_t count, const void * buff)` | -| | 0x1105 | `int file_seek(file_t, int offset, int origin)` | -| | 0x1105 | `int file_tell(file_t)` | -| Dir I/O | 0x1201 | `dir_t dir_open(const char * path)` | -| | 0x1202 | `void dir_close(dir_t)` | -| | 0x1203 | `int dir_read(dir_t, void * dir_entry)` | -| | 0x1205 | `int dir_seek(dir_t, int offset, int origin)` | -| | 0x1205 | `int dir_tell(dir_t)` | +| I/O | 0x00010000 | open | +| | 0x00010001 | close | +| | 0x00010002 | read | +| | 0x00010003 | write | +| | 0x00010004 | seek | +| | 0x00010005 | tell | +| Memory | 0x00020000 | `void * malloc(size_t size)` | +| | 0x00020001 | `void * realloc(void * ptr, size_t size)` | +| | 0x00020002 | `void free(void * ptr)` | +| Process Control | 0x00030000 | `void exit(uint8_t code)` | +| | 0x00030001 | `void abort(uint8_t code, const char * msg)` | +| | 0x00030002 | `void panic(const char * msg, const char * file, unsigned int line)` | +| | 0x00030003 | `int register_signals(void * callback)` | +| | 0x00030004 | `int getpid()` | +| Tmp Std I/O | 0x00100000 | `size_t putc(char c)` | +| | 0x00100001 | `size_t puts(const char * str)` | +| | 0x00100002 | `size_t vprintf(const char * fmt, va_list params)` | +| File I/O | 0x00110001 | `file_t file_open(const char * path, const char * mode)` | +| | 0x00110002 | `void file_close(file_t)` | +| | 0x00110003 | `size_t file_read(file_t, size_t size, size_t count, void * buff)` | +| | 0x00110004 | `size_t file_write(file_t, size_t size, size_t count, const void * buff)` | +| | 0x00110005 | `int file_seek(file_t, int offset, int origin)` | +| | 0x00110005 | `int file_tell(file_t)` | +| Dir I/O | 0x00120001 | `dir_t dir_open(const char * path)` | +| | 0x00120002 | `void dir_close(dir_t)` | +| | 0x00120003 | `int dir_read(dir_t, void * dir_entry)` | +| | 0x00120005 | `int dir_seek(dir_t, int offset, int origin)` | +| | 0x00120005 | `int dir_tell(dir_t)` | ## System Calls 2.0 diff --git a/src/kernel/include/kernel/system_call_io.h b/src/kernel/include/kernel/system_call_io.h index c64087d..a881e44 100644 --- a/src/kernel/include/kernel/system_call_io.h +++ b/src/kernel/include/kernel/system_call_io.h @@ -3,6 +3,6 @@ #include "system_call.h" -int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs); +int sys_call_io_cb(uint32_t call_id, void * args_data, registers_t * regs); #endif // KERNEL_SYSTEM_CALL_IO_H diff --git a/src/kernel/include/kernel/system_call_mem.h b/src/kernel/include/kernel/system_call_mem.h index 7bc6e04..7cac2ab 100644 --- a/src/kernel/include/kernel/system_call_mem.h +++ b/src/kernel/include/kernel/system_call_mem.h @@ -3,6 +3,6 @@ #include "system_call.h" -int sys_call_mem_cb(uint16_t int_no, void * args_data, registers_t * regs); +int sys_call_mem_cb(uint32_t call_id, void * args_data, registers_t * regs); #endif // KERNEL_SYSTEM_CALL_MEM_H diff --git a/src/kernel/include/kernel/system_call_proc.h b/src/kernel/include/kernel/system_call_proc.h index 276e07a..65bd3a0 100644 --- a/src/kernel/include/kernel/system_call_proc.h +++ b/src/kernel/include/kernel/system_call_proc.h @@ -3,6 +3,6 @@ #include "system_call.h" -int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs); +int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs); #endif // KERNEL_SYSTEM_CALL_PROC_H diff --git a/src/kernel/include/system_call.h b/src/kernel/include/system_call.h index a25bd4c..5effd11 100644 --- a/src/kernel/include/system_call.h +++ b/src/kernel/include/system_call.h @@ -6,10 +6,10 @@ #include "cpu/isr.h" #include "defs.h" -typedef int (*sys_call_handler_t)(uint16_t interrupt_no, void * args_data, registers_t * regs); +typedef int (*sys_call_handler_t)(uint32_t call_id, void * args_data, registers_t * regs); void system_call_init(uint8_t isr_interrupt_no); -void system_call_register(uint8_t family, sys_call_handler_t handler); +void system_call_register(uint16_t family, sys_call_handler_t handler); #endif // SYSTEM_CALL_H diff --git a/src/kernel/src/drivers/vga.c b/src/kernel/src/drivers/vga.c index 6ab4698..0f2c29e 100644 --- a/src/kernel/src/drivers/vga.c +++ b/src/kernel/src/drivers/vga.c @@ -50,8 +50,8 @@ void vga_clear() { } void vga_put(int index, char c, unsigned char attr) { - // idk if this is too much - KLOG_TRACE("Put character 0x%X (%c) to index %d with attr 0x%X", c, c, index, attr); + // This is way to much + // KLOG_TRACE("Put character 0x%X (%c) to index %d with attr 0x%X", c, c, index, attr); index *= 2; __screen[index] = c; __screen[index + 1] = attr; diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 4d4b0a1..88bf8cd 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -103,9 +103,9 @@ void kernel_init() { static void setup_system_calls() { system_call_init(IRQ16); - system_call_register(SYS_INT_FAMILY_IO, sys_call_io_cb); - system_call_register(SYS_INT_FAMILY_MEM, sys_call_mem_cb); - system_call_register(SYS_INT_FAMILY_PROC, sys_call_proc_cb); + system_call_register(SYS_CALL_FAMILY_IO, sys_call_io_cb); + system_call_register(SYS_CALL_FAMILY_MEM, sys_call_mem_cb); + system_call_register(SYS_CALL_FAMILY_PROC, sys_call_proc_cb); } int kernel_exec(const char * filename, size_t argc, char ** argv) { diff --git a/src/kernel/src/kernel/system_call_io.c b/src/kernel/src/kernel/system_call_io.c index 064d1b6..0194bd3 100644 --- a/src/kernel/src/kernel/system_call_io.c +++ b/src/kernel/src/kernel/system_call_io.c @@ -11,18 +11,18 @@ #undef SERVICE #define SERVICE "SYSCALL/IO" -int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { +int sys_call_io_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); arr_t * io_handles = &proc->io_handles; - KLOG_TRACE("Call from pid %u interrupt number 0x%X", proc->pid, int_no); + KLOG_TRACE("Call id 0x%X from pid %u", call_id, proc->pid); - switch (int_no) { + switch (call_id) { default: { - KLOG_WARNING("Invalid interrupt number 0x%X", int_no); + KLOG_WARNING("Invalid call id 0x%X", call_id); break; } - case SYS_INT_IO_OPEN: { + case SYS_CALL_IO_OPEN: { struct _args { const char * path; const char * mode; @@ -40,7 +40,7 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { return process_add_handle(proc, -1, 0, d); } break; - // case SYS_INT_IO_CLOSE: { + // case SYS_CALL_IO_CLOSE: { // struct _args { // int handle; // } * args = (struct _args *)args_data; @@ -60,7 +60,7 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { // return 0; // } break; - case SYS_INT_IO_READ: { + case SYS_CALL_IO_READ: { struct _args { int handle; char * buff; @@ -104,7 +104,7 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { // return d->read_fn(d->data, args->buff, args->count, args->pos); } break; - case SYS_INT_IO_WRITE: { + case SYS_CALL_IO_WRITE: { struct _args { int handle; const char * buff; @@ -127,7 +127,7 @@ int sys_call_io_cb(uint16_t int_no, void * args_data, registers_t * regs) { return d->write_fn(d->device_data, args->buff, args->count, args->pos); } break; - case SYS_INT_IO_SIZE: { + case SYS_CALL_IO_SIZE: { struct _args { int handle; const char * buff; diff --git a/src/kernel/src/kernel/system_call_mem.c b/src/kernel/src/kernel/system_call_mem.c index 43ce724..e5298da 100644 --- a/src/kernel/src/kernel/system_call_mem.c +++ b/src/kernel/src/kernel/system_call_mem.c @@ -11,17 +11,17 @@ #undef SERVICE #define SERVICE "SYSCALL/MEMORY" -int sys_call_mem_cb(uint16_t int_no, void * args_data, registers_t * regs) { +int sys_call_mem_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); - KLOG_TRACE("Call from pid %u interrupt number 0x%X", proc->pid, int_no); + KLOG_TRACE("Call id 0x%X from pid %u", call_id, proc->pid); - switch (int_no) { + switch (call_id) { default: { - KLOG_WARNING("Invalid interrupt number 0x%X", int_no); + KLOG_WARNING("Invalid call id 0x%X", call_id); break; } - case SYS_INT_MEM_MALLOC: { + case SYS_CALL_MEM_MALLOC: { struct _args { size_t size; } * args = (struct _args *)args_data; @@ -29,7 +29,7 @@ int sys_call_mem_cb(uint16_t int_no, void * args_data, registers_t * regs) { return PTR2UINT(memory_alloc(&proc->memory, args->size)); } break; - case SYS_INT_MEM_REALLOC: { + case SYS_CALL_MEM_REALLOC: { struct _args { void * ptr; size_t size; @@ -38,7 +38,7 @@ int sys_call_mem_cb(uint16_t int_no, void * args_data, registers_t * regs) { return PTR2UINT(memory_realloc(&proc->memory, args->ptr, args->size)); } break; - case SYS_INT_MEM_FREE: { + case SYS_CALL_MEM_FREE: { struct _args { void * ptr; } * args = (struct _args *)args_data; diff --git a/src/kernel/src/kernel/system_call_proc.c b/src/kernel/src/kernel/system_call_proc.c index 6073413..e0846e3 100644 --- a/src/kernel/src/kernel/system_call_proc.c +++ b/src/kernel/src/kernel/system_call_proc.c @@ -17,21 +17,21 @@ #undef SERVICE #define SERVICE "SYSCALL/PROCESS" -int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { +int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); int res = 0; - KLOG_TRACE("Call from pid %u interrupt number 0x%X", proc->pid, int_no); + KLOG_TRACE("Call id 0x%X from pid %u", call_id, proc->pid); - switch (int_no) { + switch (call_id) { default: { - KLOG_WARNING("Invalid interrupt number 0x%X", int_no); + KLOG_WARNING("Invalid call id 0x%X", call_id); break; } // TODO this isn't fully updated with task switching - case SYS_INT_PROC_EXIT: { + case SYS_CALL_PROC_EXIT: { KLOG_DEBUG("System call proc exit"); struct _args { uint8_t code; @@ -51,7 +51,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { // TODO this isn't fully updated with task switching - case SYS_INT_PROC_ABORT: { + case SYS_CALL_PROC_ABORT: { KLOG_DEBUG("System call proc abort"); struct _args { uint8_t code; @@ -72,7 +72,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { KPANIC("Unexpected return from kernel_switch_task"); } break; - case SYS_INT_PROC_PANIC: { + case SYS_CALL_PROC_PANIC: { KLOG_DEBUG("System call proc panic"); struct _args { const char * msg; @@ -98,7 +98,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { } } break; - case SYS_INT_PROC_REG_SIG: { + case SYS_CALL_PROC_REG_SIG: { KLOG_DEBUG("System call proc sig"); struct _args { signals_master_cb_t cb; @@ -106,7 +106,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { tmp_register_signals_cb(args->cb); } break; - case SYS_INT_PROC_GETPID: { + case SYS_CALL_PROC_GETPID: { // KLOG_DEBUG("System call proc getpid"); process_t * p = get_current_process(); if (!p) { @@ -115,7 +115,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { return p->pid; } break; - case SYS_INT_PROC_QUEUE_EVENT: { + case SYS_CALL_PROC_QUEUE_EVENT: { // KLOG_DEBUG("System call proc queue event"); struct _args { ebus_event_t * event; @@ -131,7 +131,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { kernel_queue_event(args->event); } break; - case SYS_INT_PROC_YIELD: { + case SYS_CALL_PROC_YIELD: { // KLOG_DEBUG("System call proc yield"); struct _args { int filter; @@ -170,7 +170,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { return has_event; } break; - case SYS_INT_PROC_EXEC: { + case SYS_CALL_PROC_EXEC: { struct _args { const char * filename; size_t argc; @@ -181,7 +181,7 @@ int sys_call_proc_cb(uint16_t int_no, void * args_data, registers_t * regs) { return kernel_exec(args->filename, args->argc, args->argv); } break; - case SYS_INT_PROC_SET_FOREGROUND: { + case SYS_CALL_PROC_SET_FOREGROUND: { struct _args { int pid; } * args = (struct _args *)args_data; diff --git a/src/kernel/src/kernel/time.c b/src/kernel/src/kernel/time.c index 72d32fa..0d6420b 100644 --- a/src/kernel/src/kernel/time.c +++ b/src/kernel/src/kernel/time.c @@ -29,6 +29,7 @@ static arr_t __timers; // timer_t static void timer_callback(registers_t * regs) { __tick++; + // TODO is this is way too much KLOG_TRACE("Timer callback, next tick is %u", __tick); for (int i = 0; i < arr_size(&__timers); i++) { diff --git a/src/kernel/src/system_call.c b/src/kernel/src/system_call.c index c393634..1a1f58e 100644 --- a/src/kernel/src/system_call.c +++ b/src/kernel/src/system_call.c @@ -30,7 +30,7 @@ void system_call_init(uint8_t isr_interrupt_no) { KLOG_DEBUG("Initialized system calls"); } -void system_call_register(uint8_t family, sys_call_handler_t handler) { +void system_call_register(uint16_t family, sys_call_handler_t handler) { KLOG_DEBUG("Registering handler for family 0x%02X", family); if (family >= MAX_CALLBACKS) { KLOG_ERROR("Cannot register handler for family 0x%02X, must be < 0x%X", family, MAX_CALLBACKS); @@ -42,12 +42,14 @@ void system_call_register(uint8_t family, sys_call_handler_t handler) { static void callback(registers_t * regs) { uint32_t res = 0; - uint16_t int_no = regs->eax & 0xffff; - uint8_t family = (regs->eax >> 8) & 0xff; + uint32_t call_id = regs->eax; + uint16_t family = (regs->eax >> 16); + + KLOG_TRACE("Received system call 0x%X", call_id); // if (family != 0x01 && family != 0x10) { // process_t * proc = get_current_process(); - // KLOG_DEBUG("Got system call 0x%04x from PID %u", (int)int_no, proc->pid); + // KLOG_DEBUG("Got system call 0x%04x from PID %u", (int)call_id, proc->pid); // } void * args_data = UINT2PTR(regs->ebx); @@ -55,10 +57,10 @@ static void callback(registers_t * regs) { sys_call_handler_t handler = __callbacks[family]; if (handler) { - res = handler(int_no, args_data, regs); + res = handler(call_id, args_data, regs); } else { - KLOG_ERROR("Failed to find handler for interrupt 0x%04X", int_no); + KLOG_ERROR("Failed to find handler for system call 0x%04X", call_id); PANIC("UNKNOWN INTERRUPT"); } diff --git a/src/libk/include/libk/defs.h b/src/libk/include/libk/defs.h index de930f0..a661b64 100644 --- a/src/libk/include/libk/defs.h +++ b/src/libk/include/libk/defs.h @@ -1,47 +1,52 @@ #ifndef LIBK_DEFS_H #define LIBK_DEFS_H -#define SYS_INT_FAMILY_IO 0x01 -#define SYS_INT_FAMILY_MEM 0x02 -#define SYS_INT_FAMILY_PROC 0x03 -#define SYS_INT_FAMILY_STDIO 0x10 -#define SYS_INT_FAMILY_IO_FILE 0x11 -#define SYS_INT_FAMILY_IO_DIR 0x12 - -#define SYS_INT_IO_OPEN 0x0100 -#define SYS_INT_IO_CLOSE 0x0101 -#define SYS_INT_IO_READ 0x0102 -#define SYS_INT_IO_WRITE 0x0103 -#define SYS_INT_IO_SIZE 0x0104 - -#define SYS_INT_MEM_MALLOC 0x0200 -#define SYS_INT_MEM_REALLOC 0x0201 -#define SYS_INT_MEM_FREE 0x0202 - -#define SYS_INT_PROC_EXIT 0x0300 -#define SYS_INT_PROC_ABORT 0x0301 -#define SYS_INT_PROC_PANIC 0x0302 -#define SYS_INT_PROC_REG_SIG 0x0303 -#define SYS_INT_PROC_GETPID 0x0304 -#define SYS_INT_PROC_QUEUE_EVENT 0x0305 -#define SYS_INT_PROC_YIELD 0x0306 -#define SYS_INT_PROC_EXEC 0x0307 -#define SYS_INT_PROC_SET_FOREGROUND 0x0308 - -// #define SYS_INT_STDIO_PUTC 0x1000 -// #define SYS_INT_STDIO_PUTS 0x1001 - -// #define SYS_INT_IO_FILE_OPEN 0x1101 -// #define SYS_INT_IO_FILE_CLOSE 0x1102 -// #define SYS_INT_IO_FILE_READ 0x1103 -// #define SYS_INT_IO_FILE_WRITE 0x1104 -// #define SYS_INT_IO_FILE_SEEK 0x1105 -// #define SYS_INT_IO_FILE_TELL 0x1106 - -// #define SYS_INT_IO_DIR_OPEN 0x1201 -// #define SYS_INT_IO_DIR_CLOSE 0x1202 -// #define SYS_INT_IO_DIR_READ 0x1203 -// #define SYS_INT_IO_DIR_SEEK 0x1205 -// #define SYS_INT_IO_DIR_TELL 0x1206 +#define SYS_CALL_FAMILY_IO 0x01 +#define SYS_CALL_FAMILY_MEM 0x02 +#define SYS_CALL_FAMILY_PROC 0x03 +#define SYS_CALL_FAMILY_STDIO 0x10 +#define SYS_CALL_FAMILY_IO_FILE 0x11 +#define SYS_CALL_FAMILY_IO_DIR 0x12 + +#define SYS_CALL_IO_OPEN 0x010000 +#define SYS_CALL_IO_CLOSE 0x010001 +#define SYS_CALL_IO_READ 0x010002 +#define SYS_CALL_IO_WRITE 0x010003 +#define SYS_CALL_IO_SIZE 0x010004 + +#define SYS_CALL_MEM_MALLOC 0x020000 +#define SYS_CALL_MEM_REALLOC 0x020001 +#define SYS_CALL_MEM_FREE 0x020002 + +#define SYS_CALL_PROC_EXIT 0x030000 +#define SYS_CALL_PROC_ABORT 0x030001 +#define SYS_CALL_PROC_PANIC 0x030002 +#define SYS_CALL_PROC_REG_SIG 0x030003 +#define SYS_CALL_PROC_GETPID 0x030004 +#define SYS_CALL_PROC_QUEUE_EVENT 0x030005 +#define SYS_CALL_PROC_YIELD 0x030006 +#define SYS_CALL_PROC_EXEC 0x030007 +#define SYS_CALL_PROC_SET_FOREGROUND 0x030008 + +#define SYS_CALL_PROC_LIST_OPEN +#define SYS_CALL_PROC_LIST_CLOSE +#define SYS_CALL_PROC_LIST_READ +#define SYS_CALL_PROC_LIST_ + +// #define SYS_CALL_STDIO_PUTC 0x1000 +// #define SYS_CALL_STDIO_PUTS 0x1001 + +// #define SYS_CALL_IO_FILE_OPEN 0x1101 +// #define SYS_CALL_IO_FILE_CLOSE 0x1102 +// #define SYS_CALL_IO_FILE_READ 0x1103 +// #define SYS_CALL_IO_FILE_WRITE 0x1104 +// #define SYS_CALL_IO_FILE_SEEK 0x1105 +// #define SYS_CALL_IO_FILE_TELL 0x1106 + +// #define SYS_CALL_IO_DIR_OPEN 0x1201 +// #define SYS_CALL_IO_DIR_CLOSE 0x1202 +// #define SYS_CALL_IO_DIR_READ 0x1203 +// #define SYS_CALL_IO_DIR_SEEK 0x1205 +// #define SYS_CALL_IO_DIR_TELL 0x1206 #endif // LIBK_DEFS_H diff --git a/src/libk/src/sys_call.c b/src/libk/src/sys_call.c index 332ec7e..0fcd231 100644 --- a/src/libk/src/sys_call.c +++ b/src/libk/src/sys_call.c @@ -8,76 +8,76 @@ #define UINT2PTR(UINT) ((void *)(UINT)) #define LUINT2PTR(UINT) UINT2PTR((uint32_t)(UINT)) -extern int send_call(uint32_t int_no, ...); -extern NO_RETURN void send_call_noret(uint32_t int_no, ...); +extern int send_call(uint32_t call_id, ...); +extern NO_RETURN void send_call_noret(uint32_t call_id, ...); int _sys_io_open(const char * path, const char * mode) { - return send_call(SYS_INT_IO_OPEN, path, mode); + return send_call(SYS_CALL_IO_OPEN, path, mode); } int _sys_io_close(int handle) { - return send_call(SYS_INT_IO_CLOSE, handle); + return send_call(SYS_CALL_IO_CLOSE, handle); } int _sys_io_read(int handle, char * buff, size_t count, size_t pos) { - return send_call(SYS_INT_IO_READ, handle, buff, count, pos); + return send_call(SYS_CALL_IO_READ, handle, buff, count, pos); } int _sys_io_write(int handle, const char * buff, size_t count, size_t pos) { - return send_call(SYS_INT_IO_WRITE, handle, buff, count, pos); + return send_call(SYS_CALL_IO_WRITE, handle, buff, count, pos); } int _sys_io_size(int handle) { - return send_call(SYS_INT_IO_SIZE, handle); + return send_call(SYS_CALL_IO_SIZE, handle); } void * _sys_mem_malloc(size_t size) { - return UINT2PTR(send_call(SYS_INT_MEM_MALLOC, size)); + return UINT2PTR(send_call(SYS_CALL_MEM_MALLOC, size)); } void * _sys_mem_realloc(void * ptr, size_t size) { - return UINT2PTR(send_call(SYS_INT_MEM_REALLOC, ptr, size)); + return UINT2PTR(send_call(SYS_CALL_MEM_REALLOC, ptr, size)); } void _sys_mem_free(void * ptr) { - send_call(SYS_INT_MEM_FREE, ptr); + send_call(SYS_CALL_MEM_FREE, ptr); } void _sys_proc_exit(uint8_t code) { // _sys_puts("libk: Proc exit\n"); - send_call_noret(SYS_INT_PROC_EXIT, code); + send_call_noret(SYS_CALL_PROC_EXIT, code); } void _sys_proc_abort(uint8_t code, const char * msg) { // _sys_puts("libk: Proc abort\n"); - send_call_noret(SYS_INT_PROC_ABORT, code, msg); + send_call_noret(SYS_CALL_PROC_ABORT, code, msg); } void _sys_proc_panic(const char * msg, const char * file, unsigned int line) { // _sys_puts("libk: Proc panic\n"); - send_call_noret(SYS_INT_PROC_PANIC, msg, file, line); + send_call_noret(SYS_CALL_PROC_PANIC, msg, file, line); } int _sys_proc_getpid(void) { - return send_call(SYS_INT_PROC_GETPID); + return send_call(SYS_CALL_PROC_GETPID); } void _sys_register_signals(void * callback) { - send_call(SYS_INT_PROC_REG_SIG, callback); + send_call(SYS_CALL_PROC_REG_SIG, callback); } void _sys_queue_event(ebus_event_t * event) { - send_call(SYS_INT_PROC_QUEUE_EVENT, event); + send_call(SYS_CALL_PROC_QUEUE_EVENT, event); } int _sys_yield(int filter, ebus_event_t * event_out) { - return send_call(SYS_INT_PROC_YIELD, filter, event_out); + return send_call(SYS_CALL_PROC_YIELD, filter, event_out); } int _sys_proc_exec(const char * filename, int argc, char ** argv) { - return send_call(SYS_INT_PROC_EXEC, filename, argc, argv); + return send_call(SYS_CALL_PROC_EXEC, filename, argc, argv); } int _sys_proc_set_foreground(int pid) { - return send_call(SYS_INT_PROC_SET_FOREGROUND, pid); + return send_call(SYS_CALL_PROC_SET_FOREGROUND, pid); } From be91bca19549de3333935db5ba09677536a7bea7 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 06:43:40 -0500 Subject: [PATCH 05/38] Cleanup makefile --- Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e2f9ca1..64e64a3 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,14 @@ QEMUFLAGS = -m 1G \ -vga cirrus \ -D qemu_log.txt \ -no-reboot -no-shutdown \ - -chardev stdio,id=char0,logfile=kernel.log,signal=off -serial chardev:char0 + -chardev stdio,id=char0,logfile=kernel.log,signal=off \ + -serial chardev:char0 + +# To write to file without stdout use +# -chardev stdout,id=char0,path=kernel.log,signal=off \ +# -serial chardev:char0 +# or +# -serial file:kernel.log # =============== # LAUNCH & UTIL From a178e66bb7aea7fcf436e72cfad47356dffa5b7d Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 07:07:40 -0500 Subject: [PATCH 06/38] Remove unused variable --- src/kernel/src/kernel/system_call_proc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/kernel/src/kernel/system_call_proc.c b/src/kernel/src/kernel/system_call_proc.c index e0846e3..6930c4a 100644 --- a/src/kernel/src/kernel/system_call_proc.c +++ b/src/kernel/src/kernel/system_call_proc.c @@ -19,7 +19,6 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); - int res = 0; KLOG_TRACE("Call id 0x%X from pid %u", call_id, proc->pid); From cbe742328a84fa130d6de0d34f43950232f1c810 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 07:34:35 -0500 Subject: [PATCH 07/38] Finish system call docs. Start signal docs --- design/signals.md | 17 +++++ design/system_call.md | 169 +++++++++++++++++++----------------------- 2 files changed, 94 insertions(+), 92 deletions(-) create mode 100644 design/signals.md diff --git a/design/signals.md b/design/signals.md new file mode 100644 index 0000000..1a2dc25 --- /dev/null +++ b/design/signals.md @@ -0,0 +1,17 @@ +# WIP - Signals + +Signals allow the kernel to communicate to the process using callbacks. To +handle communication form process to kernel, use [system calls](system_call.md). + +TODO + +- [ ] Signal callback signature +- [ ] Registering callback +- [ ] Sending signals from kernel + +# Old + +The `register_signals` call will hook a function in libc to receive all signals. +It will then store all registered callbacks of the process. + +TODO - keyboard event diff --git a/design/system_call.md b/design/system_call.md index b02eafd..d2c9e3a 100644 --- a/design/system_call.md +++ b/design/system_call.md @@ -1,12 +1,10 @@ -# WIP - System Calls +# System Calls -- [x] How system calls are defined (int no.) -- [x] How system calls are sent (wrapper) -- [ ] How system calls are receive (callback) -- [ ] System call wrapper -- [ ] Receiving args -- [ ] Returning value -- [ ] When virtual memory changes, args are invalid? Or not because it's the kernel stack +System calls are the mechanism by which processes communicate with the kernel +both for sending commands and retrieving data. Some examples include file io, +memory management, process management, etc. System calls are initiated by the +process. To handle communication form kernel to process, use +[signals](signals.md). ## Sending System Calls @@ -40,94 +38,81 @@ followed by 16 bits for the call number. ## Receiving System Calls -- handled by callback -- registered using system_call_register +System calls are received by the kernel through callbacks registered with +`system_call_register`. The callback function receives a `uint32_t` call id, +`void *` pointer to the va_args pushed onto the stack by `send_call` and +`send_call_noret`, and `registers_t *` object with values of all registers. -# OLD +```c +typedef int (*sys_call_handler_t)(uint32_t call_id, void * args_data, registers_t * regs); +void system_call_register(uint16_t family, sys_call_handler_t handler); +``` -System calls are performed through interrupt 48 (`int 0x30`). The interrupt -takes a `uint32_t` id and some number of arguments. +### Call Arguments -Each system call is defined by a function in libk which wraps the `send_call` -and `send_call_noret` functions. +Arguments are accessible from `args_data` which is a pointer to the va_args in +the caller process stack. A struct can be used to decompose the argument values +from this pointer. ```c -extern int send_call(uint32_t int_no, ...); -extern NO_RETURN void send_call_noret(uint32_t int_no, ...); +struct _args { + void * ptr; + size_t count; +} * args = (struct _args *)args_data; +// use args->ptr or args->count to read values ``` - - -TODO - max 256 callbacks per family, family is a 24 bit number -TODO - register callbacks -TODO - callback signature -TODO - accessing args in callback -TODO - args not available after page swap, need to copy anything not on the stack into kernel memory - -## System Calls - -These are calls from the process to the kernel - -> [!WARNING] This section is out of date -> See [src/libk/include/libk/defs.h](../src/libk/include/libk/defs.h) for the -> current implementation. - -| ID | Family | -| ---- | --------------- | -| 0x01 | I/O | -| 0x02 | Memory | -| 0x03 | Process Control | -| 0x10 | Tmp Std I/O | - -An interrupt id is an 8 bit family + an 8 bit id. - -| Family | ID | Name | -| --------------- | ------ | ------------------------------------------------------------------------- | -| I/O | 0x00010000 | open | -| | 0x00010001 | close | -| | 0x00010002 | read | -| | 0x00010003 | write | -| | 0x00010004 | seek | -| | 0x00010005 | tell | -| Memory | 0x00020000 | `void * malloc(size_t size)` | -| | 0x00020001 | `void * realloc(void * ptr, size_t size)` | -| | 0x00020002 | `void free(void * ptr)` | -| Process Control | 0x00030000 | `void exit(uint8_t code)` | -| | 0x00030001 | `void abort(uint8_t code, const char * msg)` | -| | 0x00030002 | `void panic(const char * msg, const char * file, unsigned int line)` | -| | 0x00030003 | `int register_signals(void * callback)` | -| | 0x00030004 | `int getpid()` | -| Tmp Std I/O | 0x00100000 | `size_t putc(char c)` | -| | 0x00100001 | `size_t puts(const char * str)` | -| | 0x00100002 | `size_t vprintf(const char * fmt, va_list params)` | -| File I/O | 0x00110001 | `file_t file_open(const char * path, const char * mode)` | -| | 0x00110002 | `void file_close(file_t)` | -| | 0x00110003 | `size_t file_read(file_t, size_t size, size_t count, void * buff)` | -| | 0x00110004 | `size_t file_write(file_t, size_t size, size_t count, const void * buff)` | -| | 0x00110005 | `int file_seek(file_t, int offset, int origin)` | -| | 0x00110005 | `int file_tell(file_t)` | -| Dir I/O | 0x00120001 | `dir_t dir_open(const char * path)` | -| | 0x00120002 | `void dir_close(dir_t)` | -| | 0x00120003 | `int dir_read(dir_t, void * dir_entry)` | -| | 0x00120005 | `int dir_seek(dir_t, int offset, int origin)` | -| | 0x00120005 | `int dir_tell(dir_t)` | - -## System Calls 2.0 - -io -- open handle -- close handle -- read handle -- write handle -- handle size? (maybe part of open) -- stat? size? (can't be seek or tell, those are in libc) - - -# System Signals - -These are callbacks from the kernel to the process. - -The `register_signals` call will hook a function in libc to receive all signals. -It will then store all registered callbacks of the process. - -TODO - keyboard event +> [!WARNING] +> +> Argument data is stored in the process stack. After changing the page directory +> the values in `arg_data` will be invalid. Copy values to the kernel stack or +> heap before switching to retrain access. + +### Return Value + +Each call handler can optionally returns a single `int` value to the caller +process by returning a value from the handler function. If no value is returned +to the caller process, the call handler should return 0. + +### Example Handler + +A typical call handler uses a switch block to select the correct logic based +on the `call_id`. + +```c +// Define handler function +int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { + // Get the caller process + process_t * proc = get_current_process(); + + // Handle call id + switch (call_id) { + // Log warning if call id is unknown + default: { + KLOG_WARNING("Invalid call id 0x%X", call_id); + break; + } + + // Logic for call id + case SYS_CALL_MEM_MALLOC: { + // va args from send_call or send_call_noret + struct _args { + size_t size; + } * args = (struct _args *)args_data; + // Return int to caller process + return PTR2UINT(memory_alloc(&proc->memory, args->size)); + } break; + + case SYS_CALL_MEM_FREE: { + struct _args { + void * ptr; + } * args = (struct _args *)args_data; + memory_free(&proc->memory, args->ptr); + // No value is returned so handler defaults to 0 + } break; + } + + // Default return value of 0 + return 0; +} +``` From 83a974febc8d99ca43813578b9bd568a30bb018f Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 07:43:53 -0500 Subject: [PATCH 08/38] Mark docs as wip, enable live reload --- design/driver.md | 2 +- design/filesystem.md | 3 +-- design/task kernel coms.md | 2 +- docs/Makefile | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/design/driver.md b/design/driver.md index af761e0..85970b7 100644 --- a/design/driver.md +++ b/design/driver.md @@ -1,4 +1,4 @@ -# Driver +# WIP - Driver Loading drivers is a future problem. Drivers will be built into the kernel and the kernel will know about each of them after compilation. diff --git a/design/filesystem.md b/design/filesystem.md index 3d995d1..048a1ab 100644 --- a/design/filesystem.md +++ b/design/filesystem.md @@ -1,5 +1,4 @@ - -# Structure +# Filesystem - Blocks are 64 bytes each - Block groups have 256 blocks (max addressable with 8 bits) diff --git a/design/task kernel coms.md b/design/task kernel coms.md index bc5935d..2523d72 100644 --- a/design/task kernel coms.md +++ b/design/task kernel coms.md @@ -1,4 +1,4 @@ -# Task and Kernel Communication +# WIP - Task and Kernel Communication ## Task to Kernel diff --git a/docs/Makefile b/docs/Makefile index 02cbc2b..856cd6c 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -6,6 +6,6 @@ build: uv run mkdocs build serve: - uv run mkdocs serve + uv run mkdocs serve --livereload .PHONY: setup build serve From d0b2a62798a352fdf5481d50afc4bfe5ac1df4bc Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 07:50:26 -0500 Subject: [PATCH 09/38] Cleanup whitespace --- design/system_call.md | 2 +- design/time.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/design/system_call.md b/design/system_call.md index d2c9e3a..fafdd15 100644 --- a/design/system_call.md +++ b/design/system_call.md @@ -92,7 +92,7 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { KLOG_WARNING("Invalid call id 0x%X", call_id); break; } - + // Logic for call id case SYS_CALL_MEM_MALLOC: { // va args from send_call or send_call_noret diff --git a/design/time.md b/design/time.md index c9b079c..8393f3f 100644 --- a/design/time.md +++ b/design/time.md @@ -15,7 +15,7 @@ the reload value, reading the current count, etc. Each channel counts down, starting at the reload value, and when they reach 0 the output is switched (low -> high or high -> low). In most cases the channel -is then set to the reload value. +is then set to the reload value. TODO in what cases is the reload value not used when a channel reaches 0? From 18d8d549c58906c8b696ec91d17c096ea3e401e1 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 07:50:39 -0500 Subject: [PATCH 10/38] Mark .clang-format as yaml --- .vscode/settings.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index ce6c30a..387ae1b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,7 @@ { + "files.associations": { + ".clang-format": "yaml" + }, "coverage-gutters.coverageReportFileName": "tests/build/os_test_coverage/index.html", "coverage-gutters.coverageBaseDir": "tests/build" } \ No newline at end of file From 52b877327e988e441be670fa156adda43f88debd Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 07:50:50 -0500 Subject: [PATCH 11/38] Link loader notes in docs --- docs/docs/loader_ntoes.md | 1 + 1 file changed, 1 insertion(+) create mode 120000 docs/docs/loader_ntoes.md diff --git a/docs/docs/loader_ntoes.md b/docs/docs/loader_ntoes.md new file mode 120000 index 0000000..d22fa9f --- /dev/null +++ b/docs/docs/loader_ntoes.md @@ -0,0 +1 @@ +../../loader_ntoes.md \ No newline at end of file From 131ccaaeeff317810a7590da7b93ac7aa74275f6 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 07:51:02 -0500 Subject: [PATCH 12/38] Update notes title --- notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes.md b/notes.md index f40f14a..a34a331 100644 --- a/notes.md +++ b/notes.md @@ -1,4 +1,4 @@ -# Notes and ToDos for active and planned future work +# Notes & Work Planning This is a list of all active and planned work. They can be removed once they are checked off. Use the task template bellow for larger tasks that need some design From be4e3c79fef3254f5642d45e8124a6f018f72485 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 07:51:14 -0500 Subject: [PATCH 13/38] Add readme for docs generation --- docs/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/README.md b/docs/README.md index e69de29..893669f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,9 @@ +# Docs Site + +This directory contains documentation site generation using mkdocs. Pages are +generated from markdown files in the project root along with design docs. + +- [Project Readme](../README.md) +- [Notes & Work Planning](../notes.md) +- [Loader Notes](../loader_ntoes.md) +- [Design Docs](../design/) From 631cc5b46369b686c60d4219650f63c54fa0337d Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 07:59:55 -0500 Subject: [PATCH 14/38] Fix loader notes filename --- docs/README.md | 2 +- docs/docs/loader_notes.md | 1 + docs/docs/loader_ntoes.md | 1 - loader_ntoes.md => loader_notes.md | 0 4 files changed, 2 insertions(+), 2 deletions(-) create mode 120000 docs/docs/loader_notes.md delete mode 120000 docs/docs/loader_ntoes.md rename loader_ntoes.md => loader_notes.md (100%) diff --git a/docs/README.md b/docs/README.md index 893669f..566dce4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,5 +5,5 @@ generated from markdown files in the project root along with design docs. - [Project Readme](../README.md) - [Notes & Work Planning](../notes.md) -- [Loader Notes](../loader_ntoes.md) +- [Loader Notes](../loader_notes.md) - [Design Docs](../design/) diff --git a/docs/docs/loader_notes.md b/docs/docs/loader_notes.md new file mode 120000 index 0000000..e05bbbd --- /dev/null +++ b/docs/docs/loader_notes.md @@ -0,0 +1 @@ +../../loader_notes.md \ No newline at end of file diff --git a/docs/docs/loader_ntoes.md b/docs/docs/loader_ntoes.md deleted file mode 120000 index d22fa9f..0000000 --- a/docs/docs/loader_ntoes.md +++ /dev/null @@ -1 +0,0 @@ -../../loader_ntoes.md \ No newline at end of file diff --git a/loader_ntoes.md b/loader_notes.md similarity index 100% rename from loader_ntoes.md rename to loader_notes.md From 1ccf69bc7a002d35a96f6d558ef360c57ccc0982 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 08:00:05 -0500 Subject: [PATCH 15/38] Add usage commands to docs readme --- docs/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/README.md b/docs/README.md index 566dce4..905a4bd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,3 +7,23 @@ generated from markdown files in the project root along with design docs. - [Notes & Work Planning](../notes.md) - [Loader Notes](../loader_notes.md) - [Design Docs](../design/) + +## Usage + +Setup + +```sh +make setup +``` + +Dev server with live reload + +```sh +make serve +``` + +Build static site + +```sh +make build +``` From 8d3154789aa9c5b764e3be54b96270ef59655dee Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 08:19:33 -0500 Subject: [PATCH 16/38] Add project structure and more usage details to readme --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index fa4fcc6..1f46b4d 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,35 @@ # os -~~Following the tutorials under https://github.com/cfenollosa/os-tutorial~~ - -Active and planned work is tracked in [notes.md](notes.md) - -For current specs see +Hobby i386 kernel / operating system. + +Project Structure + +```plaintext +├── archlinux # i386 cross compiler install for archlinux +├── cmake # Cmake utilities +├── CMakeLists.txt # Project cmake +├── design # Design concepts and implementation references +├── docs # MKDocs site generation +├── install_cross.sh # i386 cross compiler install for Ubuntu +├── Makefile # Build, test and emulator commands +├── notes.md # Active and planned work +├── README.md # Project readme +├── src # OS source code +│ ├── apps # User space programs +│ ├── boot # Boot loader +│ ├── cpu # CPU architecture specific code (i386) +│ ├── ebus # Event bus +│ ├── kernel # Loader & Kernel +│ ├── libc # C Library +│ ├── libk # Kernel Library +│ └── util # Macros, types and address defs +└── tests # OS tests +``` -- [boot.md](design/boot.md) -- ~~[filesystem.md](design/filesystem.md)~~ -- [memory.md](design/memory.md) -- [process.md](design/process.md) -- [system_call.md](design/system_call.md) +This project started by following the tutorials under +[https://github.com/cfenollosa/os-tutorial](https://github.com/cfenollosa/os-tutorial) +but has diverged quite a bit since. Some components are still mostly the same +(eg. [src/boot/](src/boot/)). ## Goals @@ -100,18 +119,30 @@ make setup ### Building +The os image can be found at `build/os-image.bin`, with an elf for the kernel +at `build/src/kernel/kernel.elf` for debug symbols. Apps are combined in a +tar file at `build/apps.tar` which is mounted by the kernel at runtime. + ```sh make build ``` ### Running +QEMU is used for cpu emulation and kernel execution. I'm using QEMU emulator +version 10.1.0 (Debian 1:10.1.0+ds-5ubuntu2.4) but other versions should work. +Logs will be written to stdout and `kernel.log` Qemu logs are written to +`qemu_logs.txt` + ```sh make run ``` Once running, use the `help` command to see what you can do. +Kernel log level can be adjusted in +[src/kernel/src/loader.c](src/kernel/src/loader.c) in the function `__start` + ### Testing ```sh From 17b790338863819f8015da6b99964631e4d9541a Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 08:23:40 -0500 Subject: [PATCH 17/38] Add missing files to project structure, add trailing / for directories in project structure --- README.md | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 1f46b4d..6d6be83 100644 --- a/README.md +++ b/README.md @@ -5,25 +5,28 @@ Hobby i386 kernel / operating system. Project Structure ```plaintext -├── archlinux # i386 cross compiler install for archlinux -├── cmake # Cmake utilities +├── .github/ # CI build, lint, testing and release +├── .vscode/ # VSCode editor config, build task and launch profile +├── archlinux/ # i386 cross compiler install for archlinux +├── cmake/ # Cmake utilities +├── design/ # Design concepts and implementation references +├── docs/ # MKDocs site generation +├── .clang-format # Formatter config ├── CMakeLists.txt # Project cmake -├── design # Design concepts and implementation references -├── docs # MKDocs site generation ├── install_cross.sh # i386 cross compiler install for Ubuntu ├── Makefile # Build, test and emulator commands ├── notes.md # Active and planned work ├── README.md # Project readme -├── src # OS source code -│ ├── apps # User space programs -│ ├── boot # Boot loader -│ ├── cpu # CPU architecture specific code (i386) -│ ├── ebus # Event bus -│ ├── kernel # Loader & Kernel -│ ├── libc # C Library -│ ├── libk # Kernel Library -│ └── util # Macros, types and address defs -└── tests # OS tests +├── src/ # OS source code +│ ├── apps/ # User space programs +│ ├── boot/ # Boot loader +│ ├── cpu/ # CPU architecture specific code (i386) +│ ├── ebus/ # Event bus +│ ├── kernel/ # Loader & Kernel +│ ├── libc/ # C Library +│ ├── libk/ # Kernel Library +│ └── util/ # Macros, types and address defs +└── tests/ # OS tests ``` This project started by following the tutorials under From c67a993e75de110944bf416825b7d1a167ca1e67 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 7 Mar 2026 10:42:12 -0500 Subject: [PATCH 18/38] Cleanup readme --- README.md | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 6d6be83..02c5ccf 100644 --- a/README.md +++ b/README.md @@ -2,32 +2,8 @@ Hobby i386 kernel / operating system. -Project Structure - -```plaintext -├── .github/ # CI build, lint, testing and release -├── .vscode/ # VSCode editor config, build task and launch profile -├── archlinux/ # i386 cross compiler install for archlinux -├── cmake/ # Cmake utilities -├── design/ # Design concepts and implementation references -├── docs/ # MKDocs site generation -├── .clang-format # Formatter config -├── CMakeLists.txt # Project cmake -├── install_cross.sh # i386 cross compiler install for Ubuntu -├── Makefile # Build, test and emulator commands -├── notes.md # Active and planned work -├── README.md # Project readme -├── src/ # OS source code -│ ├── apps/ # User space programs -│ ├── boot/ # Boot loader -│ ├── cpu/ # CPU architecture specific code (i386) -│ ├── ebus/ # Event bus -│ ├── kernel/ # Loader & Kernel -│ ├── libc/ # C Library -│ ├── libk/ # Kernel Library -│ └── util/ # Macros, types and address defs -└── tests/ # OS tests -``` +- [Active and planned work](notes.md) +- [Design concepts and implementation references](design/) This project started by following the tutorials under [https://github.com/cfenollosa/os-tutorial](https://github.com/cfenollosa/os-tutorial) From 96e3cc72db2298efc39fd34b94213f2e596baf37 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 8 Mar 2026 01:01:02 -0500 Subject: [PATCH 19/38] Document fields of process_t and kernel_t --- design/process.md | 2 ++ src/kernel/include/kernel.h | 16 +++++++++----- src/kernel/include/process.h | 43 ++++++++++++++++++++++++++++-------- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/design/process.md b/design/process.md index bbc085e..c9ef31a 100644 --- a/design/process.md +++ b/design/process.md @@ -49,6 +49,8 @@ The TSS entry will need to be updated with the new process' esp0. TODO : the ESP0 might be better stored in the kernel instead of the process if the process page dir does not include a stack for the kernel (eg. isr stack). +# Old + ## Process Struct | Start | Size | Description | diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index 29a88d3..0e6ef59 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -14,12 +14,18 @@ #include "process_manager.h" typedef struct _kernel { - uint32_t esp0; - proc_man_t pm; + /// Kernel stack pointer + uint32_t esp0; + /// Process manager + proc_man_t pm; + /// Process scheduler scheduler_t scheduler; - ebus_t event_queue; - disk_t * disk; - tar_fs_t * tar; + /// Kernel event bus (is this used?) + ebus_t event_queue; + /// Disk driver for boot drive (this is temporary and should be replaced with a proper driver / device manager) + disk_t * disk; + /// Filesystem driver for boot drive (this is temporary and should be replaced with a proper drier / filesystem manager) + tar_fs_t * tar; } kernel_t; disk_t * kernel_get_disk(); diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 7bb543a..3826741 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -30,41 +30,66 @@ typedef struct _handle { } handle_t; enum PROCESS_STATE { + /// Process struct is created but nothing is loaded PROCESS_STATE_STARTING = 0, + /// Resources are being allocated for the process PROCESS_STATE_LOADING, + /// Ready to start but not yet started PROCESS_STATE_LOADED, + /// Execution suspended, no events waited for PROCESS_STATE_SUSPENDED, + /// Execution suspended, waiting for event PROCESS_STATE_WAITING, - // PROCESS_STATE_WAITING_STDIN, + /// This is the curent active process running PROCESS_STATE_RUNNING, + /// Execution has finished, resources have not been freed PROCESS_STATE_DEAD, + /// Kernel error, resources have not been freed. User errors are noted in status_code PROCESS_STATE_ERROR, }; typedef struct _process { + /// Page directory physical address uint32_t cr3; + /// Process stack pointer uint32_t esp; + /// Kernel stack pointer? uint32_t esp0; + /// Process id uint32_t pid; + /// Virtual address of the next page to be allocated for the heap uint32_t next_heap_page; + /// Number of pages allocated to the stack uint32_t stack_page_count; // TODO heap & stack limits - char * filepath; - int argc; + /// String path to executable file on filesystem + char * filepath; + /// Number of arguments, at least 1 (for filename) + int argc; + /// Arguments to process, first arg is filename char ** argv; - int status_code; + /// Exit code after execution + int status_code; + /// Optional callback address for receiving signals from kernel signals_master_cb_t signals_callback; - arr_t io_handles; // array - ebus_t event_queue; - memory_t memory; - - uint32_t filter_event; + /// array of open io handles, access to io methods, state and driver + arr_t io_handles; // array + /// event bus for this process + ebus_t event_queue; + /// Memory allocation from the kernel (for malloc in kernel instead of libc) + memory_t memory; + + /// Event type being waited on by process if state is PROCESS_STATE_WAITING + uint32_t filter_event; + /// Current state of process (eg. loading, running, waiting, dead, etc.) enum PROCESS_STATE state; + /// Array of circular buffers used to store data being sent to each handle. + /// If a buffee is filled it ... (tbd, drops input or pops oldest?) io_buffer_t * io_buffer; } process_t; From 39e146b735e09957dd776753a8cbc1b4d0e2561c Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 8 Mar 2026 01:03:38 -0500 Subject: [PATCH 20/38] Fix log message --- src/kernel/src/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 718b231..c2d68b6 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -273,7 +273,7 @@ int process_resume(process_t * proc, const ebus_event_t * event) { return -1; } if (proc->state < PROCESS_STATE_LOADED) { - KLOG_ERROR("Process not yet started"); + KLOG_ERROR("Process not yet loaded"); return -1; } if (proc->state >= PROCESS_STATE_DEAD) { From d48c493030fb8b01489a7ef8babd6ac16ab8e4ae Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 8 Mar 2026 01:08:28 -0500 Subject: [PATCH 21/38] Only set previous process state if currently running --- src/kernel/src/process.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index c2d68b6..7ec3698 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -285,7 +285,14 @@ int process_resume(process_t * proc, const ebus_event_t * event) { if (!active_before) { KPANIC("Failed to find active task"); } - active_before->state = PROCESS_STATE_SUSPENDED; + + if (active_before->state == PROCESS_STATE_RUNNING) { + KLOG_TRACE("Setting state of active process %u to suspended", active_before->pid); + active_before->state = PROCESS_STATE_SUSPENDED; + } + else { + KLOG_TRACE("Skip updating active process %u status because it's not running, got %u", active_before->pid, active_before->state); + } KLOG_TRACE("Setting process state for pid %u to SUSPENDED", active_before->pid); From ccb50ba932b3694a429b0dfbb4adaf9b8a1bc12b Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Tue, 10 Mar 2026 22:30:39 -0400 Subject: [PATCH 22/38] Add parent pid field to process --- design/process.md | 18 ++---------------- design/task kernel coms.md | 16 ---------------- src/kernel/include/process.h | 3 +++ src/kernel/src/process.c | 2 ++ 4 files changed, 7 insertions(+), 32 deletions(-) delete mode 100644 design/task kernel coms.md diff --git a/design/process.md b/design/process.md index c9ef31a..19cfdd8 100644 --- a/design/process.md +++ b/design/process.md @@ -49,23 +49,9 @@ The TSS entry will need to be updated with the new process' esp0. TODO : the ESP0 might be better stored in the kernel instead of the process if the process page dir does not include a stack for the kernel (eg. isr stack). -# Old - -## Process Struct +TODO : parent pid -| Start | Size | Description | -| ----- | ---- | ------------------------ | -| 0 | 4 | Process Id (PID) | -| 4 | 4 | Next Heap Page | -| 8 | 4 | Stack Page Count | -| 16 | 4 | Page Directory (CR3) | -| 12 | 4 | Stack Pointer (ESP) | -| 20 | 4 | ISR Stack Pointer (ESP0) | -| 24 | 4 | Signal Callback Function | -| 28 | 4 | Pointer to next Process | - -- `Size` is in bytes. -- PID 0 is reserved for the kernel, the first proc will be pid 1 +# Old ## Memory diff --git a/design/task kernel coms.md b/design/task kernel coms.md deleted file mode 100644 index 2523d72..0000000 --- a/design/task kernel coms.md +++ /dev/null @@ -1,16 +0,0 @@ -# WIP - Task and Kernel Communication - -## Task to Kernel - -- System Call - - Ask the kernel for something or to do something - - Yields process -- Queue Event - - Signal / send data to other tasks - -## Kernel to Task - -- Signal - - Events for process lifecycle -- Events (via yield) - - Signal / data from other tasks diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 3826741..31e77e4 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -63,6 +63,9 @@ typedef struct _process { /// Number of pages allocated to the stack uint32_t stack_page_count; + /// PID of parent process (0 is no parent) + uint32_t parent_pid; + // TODO heap & stack limits /// String path to executable file on filesystem diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 7ec3698..4453788 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -77,6 +77,8 @@ int process_create(process_t * proc) { proc->next_heap_page = ADDR2PAGE(VADDR_USER_MEM); proc->stack_page_count = 1; + // TODO parent process pid + if (paging_temp_free(proc->cr3)) { KLOG_ERROR("Failed to free temporary page"); ram_page_free(proc->cr3); From e18d9841b1d508f35e72d73e4b55653633ea8622 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Fri, 13 Mar 2026 04:07:48 -0400 Subject: [PATCH 23/38] Fix paging tests --- tests/src/kernel/test_paging.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/kernel/test_paging.cpp b/tests/src/kernel/test_paging.cpp index affb097..6e09866 100644 --- a/tests/src/kernel/test_paging.cpp +++ b/tests/src/kernel/test_paging.cpp @@ -167,7 +167,7 @@ TEST_F(Paging, paging_add_pages_InvalidParameters) { EXPECT_NE(0, paging_add_pages(0, 1, 2)); // Start is after end - EXPECT_EQ(0, paging_add_pages(&dir, 2, 1)); + EXPECT_NE(0, paging_add_pages(&dir, 2, 1)); // End past dir EXPECT_NE(0, paging_add_pages(&dir, 1, MMU_DIR_SIZE * MMU_TABLE_SIZE)); @@ -239,7 +239,7 @@ TEST_F(Paging, paging_remove_pages_InvalidParameters) { EXPECT_NE(0, paging_remove_pages(0, 1, 2)); // Start past end - EXPECT_EQ(0, paging_remove_pages(&dir, 2, 1)); + EXPECT_NE(0, paging_remove_pages(&dir, 2, 1)); // End Past Dir EXPECT_NE(0, paging_remove_pages(&dir, 1, MMU_DIR_SIZE * MMU_TABLE_SIZE)); From f0bc0ac103b5c68d2212d7748086ef85d1cd44c5 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Fri, 13 Mar 2026 23:51:25 -0400 Subject: [PATCH 24/38] Use linked list for process management, key events not working --- src/kernel/include/process.h | 6 + src/kernel/include/process_manager.h | 3 +- src/kernel/src/process.c | 42 +++++ src/kernel/src/process_manager.c | 226 ++++++++++++--------------- 4 files changed, 148 insertions(+), 129 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 31e77e4..d5abde2 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -94,6 +94,9 @@ typedef struct _process { /// Array of circular buffers used to store data being sent to each handle. /// If a buffee is filled it ... (tbd, drops input or pops oldest?) io_buffer_t * io_buffer; + + struct _process * next; + struct _process * prev; } process_t; /** @@ -182,6 +185,9 @@ int process_add_handle(process_t * proc, int id, int flags, io_device_t * device handle_t * process_get_handle(process_t * proc, int id); +int process_link(process_t * proc, process_t * next); +int process_unlink(process_t * proc); + /** * @brief Set the next PID value. All future PID's will be incremented from * here. diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h index 28e0f5a..aee6382 100644 --- a/src/kernel/include/process_manager.h +++ b/src/kernel/include/process_manager.h @@ -5,11 +5,10 @@ #include #include "ebus.h" -#include "libc/datastruct/array.h" #include "process.h" typedef struct _proc_man { - arr_t task_list; // process_t * + process_t * first_task; process_t * foreground_task; } proc_man_t; diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index 4453788..c44bac3 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -557,6 +557,48 @@ static int open_stdio_handles(process_t * proc) { return 0; } +int process_link(process_t * proc, process_t * next) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!next) { + KLOG_ERROR("Next process struct is null pointer"); + return -1; + } + if (proc->next && proc->next->prev != proc) { + KLOG_ERROR("proc has a bad link, next does not link back to proc"); + return -1; + } + + next->prev = proc; + next->next = proc->next; + + proc->next->prev = next; + proc->next = next; + + return 0; +} + +int process_unlink(process_t * proc) { + if (!proc) { + KLOG_ERROR("Process struct is null pointer"); + return -1; + } + if (!proc->prev || !proc->next) { + KLOG_ERROR("Process struct is not linked"); + return -1; + } + + proc->prev->next = proc->next; + proc->next->prev = proc->prev; + + proc->next = 0; + proc->prev = 0; + + return 0; +} + static uint32_t __pid; static uint32_t next_pid() { diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 0c55065..fbaf8ad 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -10,8 +10,6 @@ #undef SERVICE #define SERVICE "KERNEL/PROCESS_MANAGER" -static int pid_arr_index(arr_t * arr, int pid); - int pm_create(proc_man_t * pm) { if (!pm) { KLOG_ERROR("Process manager struct is a null pointer"); @@ -23,11 +21,6 @@ int pm_create(proc_man_t * pm) { return -1; } - if (arr_create(&pm->task_list, 4, sizeof(process_t *))) { - KLOG_ERROR("Failed to create process manager task list array"); - return -1; - } - return 0; } @@ -40,21 +33,32 @@ process_t * pm_find_pid(proc_man_t * pm, int pid) { KLOG_WARNING("Find takes a pid >= 0, got %d", pid); return 0; } - - int i = pid_arr_index(&pm->task_list, pid); - if (i < 0) { - // TODO should this be warning or debug / trace? - KLOG_WARNING("Failed to find process pid %d", pid); + if (!pm->first_task) { + KLOG_WARNING("No processes exist in process manager, can't find pid %d", pid); return 0; } - process_t * proc; - if (arr_get(&pm->task_list, i, &proc)) { - KLOG_ERROR("Failed to get process for index %d", i); - return 0; + if (pm->foreground_task && pm->foreground_task->pid == pid) { + KLOG_TRACE("Returning foreground task for pid %u", pid); + return pm->foreground_task; + } + + process_t * proc = pm->first_task; + if (proc->pid == pid) { + KLOG_TRACE("Returning first task for pid %u", pid); + return proc; } + proc = proc->next; - return proc; + while (proc != pm->first_task) { + if (proc->pid == pid) { + return proc; + } + + proc = proc->next; + } + + return 0; } int pm_add_proc(proc_man_t * pm, process_t * proc) { @@ -67,12 +71,27 @@ int pm_add_proc(proc_man_t * pm, process_t * proc) { return -1; } - if (arr_insert(&pm->task_list, arr_size(&pm->task_list), &proc)) { - KLOG_ERROR("Failed to insert process pid %u into process manager", proc->pid); - return -1; + if (!pm->first_task) { + KLOG_INFO("Assigning first process to be %u", proc->pid); + pm->first_task = proc; + pm->foreground_task = proc; + + // Link to self + proc->next = proc; + proc->prev = proc; + return 0; } + else if (pm->first_task->next == pm->first_task) { + KLOG_DEBUG("Assigning second process to be %u", proc->pid); + pm->first_task->next = proc; + pm->first_task->prev = proc; - return 0; + proc->next = pm->first_task; + proc->prev = pm->first_task; + } + + KLOG_DEBUG("Linking last task %u to new process %u", proc->prev->pid, proc->pid); + return process_link(proc->prev, proc); } int pm_remove_proc(proc_man_t * pm, int pid) { @@ -90,13 +109,23 @@ int pm_remove_proc(proc_man_t * pm, int pid) { return -1; } - int i = pid_arr_index(&pm->task_list, pid); - if (i < 0 || arr_remove(&pm->task_list, i, 0)) { - KLOG_ERROR("Failed to remove process from task list array"); + process_t * proc = pm_find_pid(pm, pid); + if (!proc) { + KLOG_ERROR("Failed to find process for pid %u", pid); return -1; } - return 0; + if (proc == pm->first_task) { + KLOG_ERROR("Cannot remove first process"); + return -1; + } + + if (proc == pm->foreground_task) { + KLOG_ERROR("Cannot remove foreground process"); + return -1; + } + + return process_unlink(proc); } int pm_set_foreground_proc(proc_man_t * pm, int pid) { @@ -146,81 +175,46 @@ process_t * pm_get_next(proc_man_t * pm) { return 0; } - int i = pid_arr_index(&pm->task_list, get_active_task()->pid); - if (i < 0) { - KLOG_ERROR("Failed to fin index of current task"); - return 0; - } - - int start_i = i++; - - while (i != start_i) { - if (i >= arr_size(&pm->task_list)) { - i = 0; - } - - process_t * proc; - if (arr_get(&pm->task_list, i, &proc)) { - KPANIC("Failed to get proc"); - return 0; - } + process_t * proc = pm->foreground_task->next; - KLOG_TRACE("PID %u is state %x", proc->pid, proc->state); - - // if (proc->state == PROCESS_STATE_WAITING_STDIN) { - // KLOG_DEBUG("Process waiting for stdin"); - // if (io_buffer_length(proc->io_buffer) > 0) { - // KLOG_DEBUG("Process is waiting for stdin and has %u ready", io_buffer_length(proc->io_buffer)); - // return proc; - // } - // } + while (proc != pm->foreground_task) { + if (PROCESS_STATE_LOADED <= proc->state <= PROCESS_STATE_DEAD) { + uint32_t filter_event = 0; + if (ebus_queue_size(&proc->event_queue) > 0) { + ebus_event_t event; + if (ebus_peek(&proc->event_queue, &event)) { + filter_event = event.event_id; + KLOG_TRACE("Process %u has ready event of type %u", proc->pid, event.event_id); + } + else { + KLOG_ERROR("Failed to peek at process event queue which has length %u", ebus_queue_size(&proc->event_queue)); + } + } - if (proc->state == PROCESS_STATE_WAITING && ebus_queue_size(&proc->event_queue) > 0) { - ebus_event_t event; - if (ebus_peek(&proc->event_queue, &event) > 0) { - proc->state = PROCESS_STATE_SUSPENDED; + if (!proc->filter_event || proc->filter_event == filter_event) { + // TODO need to pop event from queue, then remove this if block + if (filter_event) { + KLOG_WARNING("YOU NEED TO POP EBUS EVENT %u", filter_event); + } + return proc; + } + else { + KLOG_TRACE("Process with pid %u does not match filter event %u, waiting for %u", proc->pid, filter_event, proc->filter_event); } } - - if (proc->state == PROCESS_STATE_LOADED || proc->state == PROCESS_STATE_SUSPENDED || proc->state == PROCESS_STATE_RUNNING) { - return proc; + else { + KLOG_TRACE("Process with pid %u is not alive", proc->pid); } - i++; - } - - process_t * active = get_active_task(); - if (PROCESS_STATE_LOADED <= active->state <= PROCESS_STATE_DEAD) { - return active; - } - - KPANIC("Process Loop!"); - - return 0; -} - -static int pid_arr_index(arr_t * arr, int pid) { - if (!arr) { - KLOG_ERROR("Array is a null pointer"); - return -1; - } - if (pid < 0) { - KLOG_WARNING("PID array find index takes a pid >= 0, got %d", pid); - return -1; - } - - for (int i = 0; i < arr_size(arr); i++) { - process_t * proc; - arr_get(arr, i, &proc); + proc = proc->next; + }; - if (proc->pid == pid) { - return i; - } + if (PROCESS_STATE_LOADED <= proc->state <= PROCESS_STATE_DEAD) { + KLOG_TRACE("Next process is the foreground process with pid %u", proc->pid); + return proc; } - KLOG_ERROR("Failed to find index of pid %u", pid); - - return -1; + KPANIC("Could not find process to resume"); } int pm_push_event(proc_man_t * pm, ebus_event_t * event) { @@ -233,51 +227,29 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { return -1; } - if (event->event_id = EBUS_EVENT_KEY) { - process_t * foreground = pm->foreground_task; - - KLOG_TRACE("Foreground is %u", foreground->pid); - - // if (event->key.event == KEY_EVENT_PRESS) { - // if (io_buffer_push(foreground->io_buffer, event->key.c)) { - // KLOG_WARNING("Failed to push key into io buffer"); - // return -1; - // } - // KLOG_TRACE("IO buffer is size %u", io_buffer_length(foreground->io_buffer)); - // } - - if (ebus_push(&foreground->event_queue, event)) { - KLOG_ERROR("Failed to push event to ebus for foreground process"); + if (pm->first_task->filter_event == event->event_id) { + if (ebus_push(&pm->first_task->event_queue, event)) { + KLOG_ERROR("Failed to push event of type %u to first task %u", event->event_id, pm->first_task->pid); return -1; } } - else { - process_t * active = get_active_task(); - for (size_t i = 0; i < arr_size(&pm->task_list); i++) { - process_t * proc; - arr_get(&pm->task_list, i, &proc); + process_t * proc = pm->first_task->next; - if (proc->pid == active->pid) { - continue; + while (proc != pm->first_task) { + if (proc->filter_event == event->event_id) { + if (ebus_push(&proc->event_queue, event)) { + KLOG_ERROR("Failed to push event of type %u to process %u", event->event_id, proc->pid); + return -1; } - if (proc->state <= PROCESS_STATE_LOADED || proc->state >= PROCESS_STATE_DEAD) { - continue; - } - - if (proc->filter_event == event->event_id) { - KLOG_DEBUG("Process %u was waiting for %u and got it", proc->pid, proc->filter_event); - if (ebus_push(&proc->event_queue, event)) { - KLOG_ERROR("Failed to push event to ebus for process %u", proc->pid); - return -1; - } - - if (proc->state == PROCESS_STATE_WAITING) { - proc->state = PROCESS_STATE_SUSPENDED; - } + if (proc->state == PROCESS_STATE_WAITING) { + KLOG_TRACE("Setting process state to suspended for pid %u", proc->pid); + proc->state = PROCESS_STATE_SUSPENDED; } } + + proc = proc->next; } return 0; From 0b81ab0f1cf50f31ee953504ccdd8e429cde076c Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sat, 14 Mar 2026 00:21:35 -0400 Subject: [PATCH 25/38] Replace event queue with single event in process struct --- src/kernel/include/process.h | 4 +- src/kernel/include/process_manager.h | 2 +- src/kernel/src/exec.c | 2 +- src/kernel/src/kernel/system_call_proc.c | 18 +++++--- src/kernel/src/process.c | 20 ++++---- src/kernel/src/process_manager.c | 58 ++++++++++++------------ 6 files changed, 57 insertions(+), 47 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index d5abde2..57d3314 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -82,12 +82,14 @@ typedef struct _process { /// array of open io handles, access to io methods, state and driver arr_t io_handles; // array /// event bus for this process - ebus_t event_queue; + // ebus_t event_queue; /// Memory allocation from the kernel (for malloc in kernel instead of libc) memory_t memory; /// Event type being waited on by process if state is PROCESS_STATE_WAITING uint32_t filter_event; + /// Event matching filter_event if one is ready + ebus_event_t next_event; /// Current state of process (eg. loading, running, waiting, dead, etc.) enum PROCESS_STATE state; diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h index aee6382..d9e95a3 100644 --- a/src/kernel/include/process_manager.h +++ b/src/kernel/include/process_manager.h @@ -23,7 +23,7 @@ int pm_remove_proc(proc_man_t * pm, int pid); int pm_set_foreground_proc(proc_man_t * pm, int pid); -int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event); +int pm_resume_process(proc_man_t * pm, int pid); // TODO move to scheduler process_t * pm_get_next(proc_man_t * pm); diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index f92f031..4178848 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -112,7 +112,7 @@ int command_exec(uint8_t * buff, const char * filepath, size_t size, size_t argc return -1; } - if (pm_resume_process(kernel_get_proc_man(), proc->pid, 0)) { + if (pm_resume_process(kernel_get_proc_man(), proc->pid)) { KLOG_ERROR("Failed to resume process %u", proc->pid); if (process_free(proc)) { KPANIC("Failed to free process while handling resume error"); diff --git a/src/kernel/src/kernel/system_call_proc.c b/src/kernel/src/kernel/system_call_proc.c index 6930c4a..ca7274b 100644 --- a/src/kernel/src/kernel/system_call_proc.c +++ b/src/kernel/src/kernel/system_call_proc.c @@ -138,21 +138,27 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { } * args = (struct _args *)args_data; // TODO clear iret from stack? + kmemset(&proc->next_event, 0, sizeof(ebus_event_t)); proc->filter_event = args->filter; proc->state = (args->filter ? PROCESS_STATE_WAITING : PROCESS_STATE_SUSPENDED); // process_yield(proc, regs->esp, regs->eip, args->filter); enable_interrupts(); process_t * next = pm_get_next(kernel_get_proc_man()); int has_event = 0; - if (ebus_queue_size(&next->event_queue) > 0) { - // KLOGS_DEBUG("SC_PROC", "Got %u events", ebus_queue_size(&next->event_queue)); - if (ebus_pop(&next->event_queue, args->event_out)) { - KPANIC("Yea, that didn't work"); + if (next->filter_event) { + if (next->next_event.event_id != next->filter_event) { + KPANIC("Tried to resume process but the event does not match filter"); } - has_event = 1; + if (args->event_out) { + // TODO log + kmemcpy(&next->next_event, args->event_out, sizeof(ebus_event_t)); + } + next->filter_event = 0; + next->next_event.event_id = 0; + has_event = 1; } // KLOGS_DEBUG("SC_PROC", "Switching from process %u to %u", proc->pid, next->pid); - if (pm_resume_process(kernel_get_proc_man(), next->pid, 0)) { + if (pm_resume_process(kernel_get_proc_man(), next->pid)) { KPANIC("Failed to resume process"); } diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index c44bac3..c5e06b2 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -91,16 +91,16 @@ int process_create(process_t * proc) { return -1; } - if (ebus_create(&proc->event_queue, 4096)) { - KLOG_ERROR("Failed to create ebus for process event queue"); - arr_free(&proc->io_handles); - ram_page_free(proc->cr3); - return -1; - } + // if (ebus_create(&proc->event_queue, 4096)) { + // KLOG_ERROR("Failed to create ebus for process event queue"); + // arr_free(&proc->io_handles); + // ram_page_free(proc->cr3); + // return -1; + // } if (memory_init(&proc->memory, kernel_alloc_page)) { KLOG_ERROR("Failed to initialize malloc for process"); - ebus_free(&proc->event_queue); + // ebus_free(&proc->event_queue); arr_free(&proc->io_handles); ram_page_free(proc->cr3); return -1; @@ -109,7 +109,7 @@ int process_create(process_t * proc) { proc->io_buffer = io_buffer_create(IO_BUFFER_SIZE); if (!proc->io_buffer) { KLOG_ERROR("Failed to create io buffer"); - ebus_free(&proc->event_queue); + // ebus_free(&proc->event_queue); arr_free(&proc->io_handles); ram_page_free(proc->cr3); return -1; @@ -117,7 +117,7 @@ int process_create(process_t * proc) { if (open_stdio_handles(proc)) { KLOG_ERROR("Failed to open stdio handles"); - ebus_free(&proc->event_queue); + // ebus_free(&proc->event_queue); arr_free(&proc->io_handles); ram_page_free(proc->cr3); io_buffer_free(proc->io_buffer); @@ -133,7 +133,7 @@ int process_free(process_t * proc) { return -1; } - ebus_free(&proc->event_queue); + // ebus_free(&proc->event_queue); arr_free(&proc->io_handles); mmu_dir_t * dir = paging_temp_map(proc->cr3); diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index fbaf8ad..b0b8202 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -149,7 +149,7 @@ int pm_set_foreground_proc(proc_man_t * pm, int pid) { return 0; } -int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { +int pm_resume_process(proc_man_t * pm, int pid) { if (!pm) { KLOG_ERROR("Process manager struct is a null pointer"); return -1; @@ -166,7 +166,14 @@ int pm_resume_process(proc_man_t * pm, int pid, ebus_event_t * event) { return -1; } - return process_resume(proc, event); + if (proc->filter_event > 0) { + // TODO assert next_event has an event of the correct type + // TODO push to process next_event instead of event_queue + // TODO clear next_event before resuming process + // TODO does process state need updating? - probably not + } + + return process_resume(proc, 0); } process_t * pm_get_next(proc_man_t * pm) { @@ -179,28 +186,19 @@ process_t * pm_get_next(proc_man_t * pm) { while (proc != pm->foreground_task) { if (PROCESS_STATE_LOADED <= proc->state <= PROCESS_STATE_DEAD) { - uint32_t filter_event = 0; - if (ebus_queue_size(&proc->event_queue) > 0) { - ebus_event_t event; - if (ebus_peek(&proc->event_queue, &event)) { - filter_event = event.event_id; - KLOG_TRACE("Process %u has ready event of type %u", proc->pid, event.event_id); - } - else { - KLOG_ERROR("Failed to peek at process event queue which has length %u", ebus_queue_size(&proc->event_queue)); - } - } - - if (!proc->filter_event || proc->filter_event == filter_event) { - // TODO need to pop event from queue, then remove this if block - if (filter_event) { - KLOG_WARNING("YOU NEED TO POP EBUS EVENT %u", filter_event); - } + if (proc->filter_event == proc->next_event.event_id) { return proc; } - else { - KLOG_TRACE("Process with pid %u does not match filter event %u, waiting for %u", proc->pid, filter_event, proc->filter_event); - } + // if (!proc->filter_event || proc->filter_event == filter_event) { + // // TODO need to pop event from queue, then remove this if block + // if (filter_event) { + // KLOG_WARNING("YOU NEED TO POP EBUS EVENT %u", filter_event); + // } + // return proc; + // } + // else { + // KLOG_TRACE("Process with pid %u does not match filter event %u, waiting for %u", proc->pid, filter_event, proc->filter_event); + // } } else { KLOG_TRACE("Process with pid %u is not alive", proc->pid); @@ -226,22 +224,26 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { KLOG_ERROR("Event is a null pointer"); return -1; } + if (!event->event_id) { + KLOG_ERROR("Event id must be non-zero"); + return -1; + } if (pm->first_task->filter_event == event->event_id) { - if (ebus_push(&pm->first_task->event_queue, event)) { - KLOG_ERROR("Failed to push event of type %u to first task %u", event->event_id, pm->first_task->pid); - return -1; + if (!pm->first_task->next_event.event_id) { + KLOG_WARNING("Replacing event %u with %u for process %u", pm->first_task->next_event.event_id, event->event_id, pm->first_task->pid); } + kmemcpy(event, &pm->first_task->next_event, sizeof(ebus_event_t)); } process_t * proc = pm->first_task->next; while (proc != pm->first_task) { if (proc->filter_event == event->event_id) { - if (ebus_push(&proc->event_queue, event)) { - KLOG_ERROR("Failed to push event of type %u to process %u", event->event_id, proc->pid); - return -1; + if (!proc->next_event.event_id) { + KLOG_WARNING("Replacing event %u with %u for process %u", proc->next_event.event_id, event->event_id, proc->pid); } + kmemcpy(event, &proc->next_event, sizeof(ebus_event_t)); if (proc->state == PROCESS_STATE_WAITING) { KLOG_TRACE("Setting process state to suspended for pid %u", proc->pid); From 5b41bc871d9de39d8252a95d2bb44da37c8c45fc Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 15 Mar 2026 11:55:53 -0400 Subject: [PATCH 26/38] Enable per file log level in logging macros --- src/cpu/i386/src/isr.c | 5 +- src/kernel/include/kernel/logs.h | 65 +++++++++++++++--------- src/kernel/src/drivers/ata.c | 5 +- src/kernel/src/drivers/keyboard.c | 5 +- src/kernel/src/drivers/pit.c | 5 +- src/kernel/src/drivers/ram.c | 5 +- src/kernel/src/drivers/ramdisk.c | 5 +- src/kernel/src/drivers/rtc.c | 5 +- src/kernel/src/drivers/tar.c | 5 +- src/kernel/src/drivers/vga.c | 5 +- src/kernel/src/exec.c | 5 +- src/kernel/src/kernel.c | 4 +- src/kernel/src/kernel/memory.c | 5 +- src/kernel/src/kernel/scheduler.c | 4 +- src/kernel/src/kernel/system_call_io.c | 5 +- src/kernel/src/kernel/system_call_mem.c | 5 +- src/kernel/src/kernel/system_call_proc.c | 46 +++-------------- src/kernel/src/kernel/time.c | 4 +- src/kernel/src/loader.c | 7 ++- src/kernel/src/paging.c | 5 +- src/kernel/src/process.c | 5 +- src/kernel/src/process_manager.c | 23 +++------ src/kernel/src/system_call.c | 5 +- 23 files changed, 94 insertions(+), 139 deletions(-) diff --git a/src/cpu/i386/src/isr.c b/src/cpu/i386/src/isr.c index d43155d..d8dd8f3 100644 --- a/src/cpu/i386/src/isr.c +++ b/src/cpu/i386/src/isr.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/ISR" + #include "cpu/isr.h" #include "cpu/idt.h" @@ -7,9 +9,6 @@ #include "libc/proc.h" #include "libc/stdio.h" -#undef SERVICE -#define SERVICE "DRIVER/ISR" - // static void print_trace(registers_t *); static isr_t __interrupt_handlers[256]; diff --git a/src/kernel/include/kernel/logs.h b/src/kernel/include/kernel/logs.h index e27346f..619aa66 100644 --- a/src/kernel/include/kernel/logs.h +++ b/src/kernel/include/kernel/logs.h @@ -4,37 +4,56 @@ #include #include -enum KERNEL_LOG_LEVEL { - KERNEL_LOG_LEVEL_TRACE = 0, - KERNEL_LOG_LEVEL_DEBUG, - KERNEL_LOG_LEVEL_INFO, - KERNEL_LOG_LEVEL_WARNING, - KERNEL_LOG_LEVEL_ERROR, - - KERNEL_LOG_LEVEL__LENGTH, // Number of log levels, used to bounds check name lookup -}; +#define KERNEL_LOG_LEVEL_TRACE 0 +#define KERNEL_LOG_LEVEL_DEBUG 1 +#define KERNEL_LOG_LEVEL_INFO 2 +#define KERNEL_LOG_LEVEL_WARNING 3 +#define KERNEL_LOG_LEVEL_ERROR 4 +#define KERNEL_LOG_LEVEL__LENGTH 5 // Number of log levels, used to bounds check name lookup #define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE2(x) #x #define LINE_STRING STRINGIZE(__LINE__) #define PREFIX __BASE_FILE__ ":" LINE_STRING -#ifndef SERVICE -#define SERVICE 0 +#ifndef KLOG_SERVICE +#define KLOG_SERVICE 0 +#endif + +#ifndef KLOG_LEVEL +#define KLOG_LEVEL KERNEL_LOG_LEVEL_DEBUG +#endif + +#define VA_ARGS(...) , ##__VA_ARGS__ +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_TRACE +#define KLOG_TRACE(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_TRACE, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_TRACE(FMT, ...) +#endif + +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_DEBUG +#define KLOG_DEBUG(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_DEBUG, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_DEBUG(FMT, ...) +#endif + +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_INFO +#define KLOG_INFO(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_INFO, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_INFO(FMT, ...) #endif -#define VA_ARGS(...) , ##__VA_ARGS__ -#define KLOG_TRACE(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_TRACE, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOG_DEBUG(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_DEBUG, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOG_INFO(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_INFO, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOG_WARNING(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_WARNING, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOG_ERROR(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_ERROR, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) - -#define KLOGS_TRACE(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_TRACE, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOGS_DEBUG(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_DEBUG, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOGS_INFO(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_INFO, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOGS_WARNING(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_WARNING, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) -#define KLOGS_ERROR(SERVICE, FMT, ...) kernel_log(KERNEL_LOG_LEVEL_ERROR, (__FILE__), (__LINE__), (SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_WARNING +#define KLOG_WARNING(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_WARNING, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_WARNING(FMT, ...) +#endif + +#if KLOG_LEVEL <= KERNEL_LOG_LEVEL_ERROR +#define KLOG_ERROR(FMT, ...) kernel_log(KERNEL_LOG_LEVEL_ERROR, (__FILE__), (__LINE__), (KLOG_SERVICE), (FMT)VA_ARGS(__VA_ARGS__)) +#else +#define KLOG_ERROR(FMT, ...) +#endif void kernel_log_init(); diff --git a/src/kernel/src/drivers/ata.c b/src/kernel/src/drivers/ata.c index 525416d..deb1d86 100644 --- a/src/kernel/src/drivers/ata.c +++ b/src/kernel/src/drivers/ata.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/ATA" + #include "drivers/ata.h" #include "cpu/isr.h" @@ -12,9 +14,6 @@ #include "libc/stdio.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/ATA" - // https://wiki.osdev.org/ATA_PIO_Mode #define MAX_RETRY 5000 diff --git a/src/kernel/src/drivers/keyboard.c b/src/kernel/src/drivers/keyboard.c index 781ef14..a260a1c 100644 --- a/src/kernel/src/drivers/keyboard.c +++ b/src/kernel/src/drivers/keyboard.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/KEYBOARD" + #include "drivers/keyboard.h" #include @@ -10,9 +12,6 @@ #include "libc/stdio.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/KEYBOARD" - static bool __e0_mode; static uint32_t __keystate[8]; static char __keyMap[0xFF] = {0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '+', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; diff --git a/src/kernel/src/drivers/pit.c b/src/kernel/src/drivers/pit.c index 7e5d9c7..91e4aa2 100644 --- a/src/kernel/src/drivers/pit.c +++ b/src/kernel/src/drivers/pit.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/PIT" + #include "drivers/pit.h" #include "cpu/isr.h" @@ -6,9 +8,6 @@ #include "kernel/panic.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/PIT" - #define PIT_CHANNEL_0_PORT 0x40 #define PIT_CHANNEL_1_PORT 0x41 #define PIT_CHANNEL_2_PORT 0x42 diff --git a/src/kernel/src/drivers/ram.c b/src/kernel/src/drivers/ram.c index 081a3da..ebb13ad 100644 --- a/src/kernel/src/drivers/ram.c +++ b/src/kernel/src/drivers/ram.c @@ -1,12 +1,11 @@ +#define KLOG_SERVICE "DRIVER/RAM" + #include "drivers/ram.h" #include "cpu/mmu.h" #include "kernel/logs.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/RAM" - #define REGION_MAX_PAGE_COUNT 0x8000 #define REGION_MAX_SIZE (REGION_MAX_PAGE_COUNT * PAGE_SIZE) diff --git a/src/kernel/src/drivers/ramdisk.c b/src/kernel/src/drivers/ramdisk.c index bb2311e..9f6ff26 100644 --- a/src/kernel/src/drivers/ramdisk.c +++ b/src/kernel/src/drivers/ramdisk.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/RAMDISK" + #include "drivers/ramdisk.h" #include "kernel.h" @@ -6,9 +8,6 @@ #include "libc/proc.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/RAMDISK" - struct _ramdisk { int id; size_t size; diff --git a/src/kernel/src/drivers/rtc.c b/src/kernel/src/drivers/rtc.c index d0a2f1f..87b6feb 100644 --- a/src/kernel/src/drivers/rtc.c +++ b/src/kernel/src/drivers/rtc.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/RTC" + #include "drivers/rtc.h" #include @@ -6,9 +8,6 @@ #include "cpu/ports.h" #include "kernel/logs.h" -#undef SERVICE -#define SERVICE "DRIVER/RTC" - #define RTC_REG_PORT 0x70 #define RTC_DATA_PORT 0x71 diff --git a/src/kernel/src/drivers/tar.c b/src/kernel/src/drivers/tar.c index fa000c4..5fb822f 100644 --- a/src/kernel/src/drivers/tar.c +++ b/src/kernel/src/drivers/tar.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/TAR" + #include "drivers/tar.h" #include @@ -9,9 +11,6 @@ #include "libc/stdio.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "DRIVER/TAR" - typedef struct { char filename[100]; char mode[8]; diff --git a/src/kernel/src/drivers/vga.c b/src/kernel/src/drivers/vga.c index 0f2c29e..b98710c 100644 --- a/src/kernel/src/drivers/vga.c +++ b/src/kernel/src/drivers/vga.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "DRIVER/VGA" + #include "drivers/vga.h" #include "cpu/ports.h" @@ -7,9 +9,6 @@ // WARNING vga driver was previously used in logging, so be careful using it for // log outputs. -#undef SERVICE -#define SERVICE "DRIVER/VGA" - #define REG_SCREEN_CTRL 0x3d4 #define REG_SCREEN_DATA 0x3d5 diff --git a/src/kernel/src/exec.c b/src/kernel/src/exec.c index 4178848..c8e7e33 100644 --- a/src/kernel/src/exec.c +++ b/src/kernel/src/exec.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "KERNEL/EXEC" + #include "exec.h" #include "cpu/mmu.h" @@ -12,9 +14,6 @@ #include "paging.h" #include "process.h" -#undef SERVICE -#define SERVICE "KERNEL/EXEC" - typedef int (*ff_t)(size_t argc, char ** argv); static void proc_entry(); diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 88bf8cd..1f988c5 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -3,6 +3,7 @@ * * Documentation moved to design/boot_stages.md */ +#define KLOG_SERVICE "KERNEL" #include "kernel.h" @@ -24,9 +25,6 @@ #include "libc/string.h" #include "libk/defs.h" -#undef SERVICE -#define SERVICE "KERNEL" - static kernel_t __kernel; extern _Noreturn void halt(void); diff --git a/src/kernel/src/kernel/memory.c b/src/kernel/src/kernel/memory.c index 28727a4..2b520f3 100644 --- a/src/kernel/src/kernel/memory.c +++ b/src/kernel/src/kernel/memory.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "KERNEL/MEMORY" + #include "kernel/memory.h" #include "kernel.h" @@ -5,9 +7,6 @@ #include "libc/memory.h" #include "paging.h" -#undef SERVICE -#define SERVICE "KERNEL/MEMORY" - static memory_t __memory; static size_t __next_heap_page; diff --git a/src/kernel/src/kernel/scheduler.c b/src/kernel/src/kernel/scheduler.c index fcffe9f..a38e597 100644 --- a/src/kernel/src/kernel/scheduler.c +++ b/src/kernel/src/kernel/scheduler.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SCHEDULER" + #include "kernel/scheduler.h" #include "ebus.h" @@ -26,7 +28,7 @@ int scheduler_run(scheduler_t * scheduler) { } if (cb_len(&get_kernel()->event_queue.queue) > 0) { - KLOGS_DEBUG("Scheduler", "There are %u events ready", cb_len(&get_kernel()->event_queue.queue)); + KLOG_DEBUG("There are %u events ready", cb_len(&get_kernel()->event_queue.queue)); ebus_event_t event; if (cb_pop(&get_kernel()->event_queue.queue, &event) < 0) { diff --git a/src/kernel/src/kernel/system_call_io.c b/src/kernel/src/kernel/system_call_io.c index 0194bd3..c6d3ba6 100644 --- a/src/kernel/src/kernel/system_call_io.c +++ b/src/kernel/src/kernel/system_call_io.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SYSCALL/IO" + #include "kernel/system_call_io.h" #include "drivers/vga.h" @@ -8,9 +10,6 @@ #include "libk/defs.h" #include "process.h" -#undef SERVICE -#define SERVICE "SYSCALL/IO" - int sys_call_io_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); arr_t * io_handles = &proc->io_handles; diff --git a/src/kernel/src/kernel/system_call_mem.c b/src/kernel/src/kernel/system_call_mem.c index e5298da..95de59e 100644 --- a/src/kernel/src/kernel/system_call_mem.c +++ b/src/kernel/src/kernel/system_call_mem.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SYSCALL/MEMORY" + #include "kernel/system_call_mem.h" #include @@ -8,9 +10,6 @@ #include "memory_alloc.h" #include "process.h" -#undef SERVICE -#define SERVICE "SYSCALL/MEMORY" - int sys_call_mem_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); diff --git a/src/kernel/src/kernel/system_call_proc.c b/src/kernel/src/kernel/system_call_proc.c index ca7274b..a822da0 100644 --- a/src/kernel/src/kernel/system_call_proc.c +++ b/src/kernel/src/kernel/system_call_proc.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SYSCALL/PROCESS" + #include "kernel/system_call_proc.h" #include @@ -14,9 +16,6 @@ #include "libk/defs.h" #include "process.h" -#undef SERVICE -#define SERVICE "SYSCALL/PROCESS" - int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { process_t * proc = get_current_process(); @@ -131,48 +130,15 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { } break; case SYS_CALL_PROC_YIELD: { - // KLOG_DEBUG("System call proc yield"); - struct _args { - int filter; - ebus_event_t * event_out; - } * args = (struct _args *)args_data; + proc->filter_event.event_id = 0; + proc->next_event.event_id = 0; + proc->state = PROCESS_STATE_SUSPENDED; - // TODO clear iret from stack? - kmemset(&proc->next_event, 0, sizeof(ebus_event_t)); - proc->filter_event = args->filter; - proc->state = (args->filter ? PROCESS_STATE_WAITING : PROCESS_STATE_SUSPENDED); - // process_yield(proc, regs->esp, regs->eip, args->filter); enable_interrupts(); - process_t * next = pm_get_next(kernel_get_proc_man()); - int has_event = 0; - if (next->filter_event) { - if (next->next_event.event_id != next->filter_event) { - KPANIC("Tried to resume process but the event does not match filter"); - } - if (args->event_out) { - // TODO log - kmemcpy(&next->next_event, args->event_out, sizeof(ebus_event_t)); - } - next->filter_event = 0; - next->next_event.event_id = 0; - has_event = 1; - } - // KLOGS_DEBUG("SC_PROC", "Switching from process %u to %u", proc->pid, next->pid); + process_t * next = pm_get_next(kernel_get_proc_man()); if (pm_resume_process(kernel_get_proc_man(), next->pid)) { KPANIC("Failed to resume process"); } - - // TODO return 1 for event out - // proc = get_current_process(); - // if (ebus_queue_size(&proc->event_queue) > 0) { - // if (ebus_pop(&proc->event_queue, args->event_out)) { - // return -1; - // } - // if (args->event_out) { - // return args->event_out->event_id; - // } - // } - return has_event; } break; case SYS_CALL_PROC_EXEC: { diff --git a/src/kernel/src/kernel/time.c b/src/kernel/src/kernel/time.c index 0d6420b..a62142f 100644 --- a/src/kernel/src/kernel/time.c +++ b/src/kernel/src/kernel/time.c @@ -1,3 +1,4 @@ +#define KLOG_SERVICE "KERNEL/TIME" #include "kernel/time.h" #include "cpu/isr.h" @@ -9,9 +10,6 @@ #include "libc/proc.h" #include "libc/stdio.h" -#undef SERVICE -#define SERVICE "KERNEL/TIME" - // https://wiki.osdev.org/PIT #define BASE_FREQ 1193180 diff --git a/src/kernel/src/loader.c b/src/kernel/src/loader.c index 11b4ebe..bd64a03 100644 --- a/src/kernel/src/loader.c +++ b/src/kernel/src/loader.c @@ -4,6 +4,7 @@ * * Documentation moved to design/boot_stages.md */ +#define KLOG_SERVICE "LOADER" #include @@ -26,9 +27,6 @@ #include "process.h" #include "process_manager.h" -#undef SERVICE -#define SERVICE "LOADER" - void kernel_init(); static void map_kernel_table(mmu_table_t * table); @@ -47,7 +45,8 @@ void __start() { serial_init(SERIAL_PORT_COM1); _libc_config_file_write_call(device_serial_write_raw); - kernel_log_set_level(KERNEL_LOG_LEVEL_DEBUG); + // THIS WAS REPLACED WITH KLOG_LEVEL MACRO + // kernel_log_set_level(KERNEL_LOG_LEVEL_DEBUG); // kernel_log_set_level(KERNEL_LOG_LEVEL_TRACE); KLOG_INFO("Loader Start"); diff --git a/src/kernel/src/paging.c b/src/kernel/src/paging.c index b455584..482b4e3 100644 --- a/src/kernel/src/paging.c +++ b/src/kernel/src/paging.c @@ -1,12 +1,11 @@ +#define KLOG_SERVICE "KERNEL/PAGING" + #include "paging.h" #include "drivers/ram.h" #include "kernel/logs.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "KERNEL/PAGING" - typedef struct { uint32_t addr; size_t count; diff --git a/src/kernel/src/process.c b/src/kernel/src/process.c index c5e06b2..6a24f2e 100644 --- a/src/kernel/src/process.c +++ b/src/kernel/src/process.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "KERNEL/PROCESS" + #include "process.h" #include "cpu/mmu.h" @@ -11,9 +13,6 @@ #include "libk/sys_call.h" #include "paging.h" -#undef SERVICE -#define SERVICE "KERNEL/PROCESS" - static int open_stdio_handles(process_t * proc); static uint32_t next_pid(); diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index b0b8202..4217b30 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "KERNEL/PROCESS_MANAGER" + #include "process_manager.h" #include "drivers/keyboard.h" @@ -7,9 +9,6 @@ #include "libc/stdio.h" #include "libc/string.h" -#undef SERVICE -#define SERVICE "KERNEL/PROCESS_MANAGER" - int pm_create(proc_man_t * pm) { if (!pm) { KLOG_ERROR("Process manager struct is a null pointer"); @@ -166,7 +165,7 @@ int pm_resume_process(proc_man_t * pm, int pid) { return -1; } - if (proc->filter_event > 0) { + if (proc->filter_event.event_id) { // TODO assert next_event has an event of the correct type // TODO push to process next_event instead of event_queue // TODO clear next_event before resuming process @@ -186,19 +185,9 @@ process_t * pm_get_next(proc_man_t * pm) { while (proc != pm->foreground_task) { if (PROCESS_STATE_LOADED <= proc->state <= PROCESS_STATE_DEAD) { - if (proc->filter_event == proc->next_event.event_id) { + if (proc->filter_event.event_id == proc->next_event.event_id) { return proc; } - // if (!proc->filter_event || proc->filter_event == filter_event) { - // // TODO need to pop event from queue, then remove this if block - // if (filter_event) { - // KLOG_WARNING("YOU NEED TO POP EBUS EVENT %u", filter_event); - // } - // return proc; - // } - // else { - // KLOG_TRACE("Process with pid %u does not match filter event %u, waiting for %u", proc->pid, filter_event, proc->filter_event); - // } } else { KLOG_TRACE("Process with pid %u is not alive", proc->pid); @@ -229,7 +218,7 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { return -1; } - if (pm->first_task->filter_event == event->event_id) { + if (pm->first_task->filter_event.event_id == event->event_id) { if (!pm->first_task->next_event.event_id) { KLOG_WARNING("Replacing event %u with %u for process %u", pm->first_task->next_event.event_id, event->event_id, pm->first_task->pid); } @@ -239,7 +228,7 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { process_t * proc = pm->first_task->next; while (proc != pm->first_task) { - if (proc->filter_event == event->event_id) { + if (proc->filter_event.event_id == event->event_id) { if (!proc->next_event.event_id) { KLOG_WARNING("Replacing event %u with %u for process %u", proc->next_event.event_id, event->event_id, proc->pid); } diff --git a/src/kernel/src/system_call.c b/src/kernel/src/system_call.c index 1a1f58e..8f65020 100644 --- a/src/kernel/src/system_call.c +++ b/src/kernel/src/system_call.c @@ -1,3 +1,5 @@ +#define KLOG_SERVICE "SYSCALL" + #include "system_call.h" #include "cpu/isr.h" @@ -11,9 +13,6 @@ #include "libk/defs.h" #include "process.h" -#undef SERVICE -#define SERVICE "SYSCALL" - #define MAX_CALLBACKS 0x100 static sys_call_handler_t __callbacks[MAX_CALLBACKS]; From a8e34475e3125e7a2e2b05b3bf10072edc85f8fa Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 15 Mar 2026 11:58:00 -0400 Subject: [PATCH 27/38] Use family def in sys call defs --- src/libk/include/libk/defs.h | 38 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libk/include/libk/defs.h b/src/libk/include/libk/defs.h index a661b64..05b936e 100644 --- a/src/libk/include/libk/defs.h +++ b/src/libk/include/libk/defs.h @@ -8,25 +8,25 @@ #define SYS_CALL_FAMILY_IO_FILE 0x11 #define SYS_CALL_FAMILY_IO_DIR 0x12 -#define SYS_CALL_IO_OPEN 0x010000 -#define SYS_CALL_IO_CLOSE 0x010001 -#define SYS_CALL_IO_READ 0x010002 -#define SYS_CALL_IO_WRITE 0x010003 -#define SYS_CALL_IO_SIZE 0x010004 - -#define SYS_CALL_MEM_MALLOC 0x020000 -#define SYS_CALL_MEM_REALLOC 0x020001 -#define SYS_CALL_MEM_FREE 0x020002 - -#define SYS_CALL_PROC_EXIT 0x030000 -#define SYS_CALL_PROC_ABORT 0x030001 -#define SYS_CALL_PROC_PANIC 0x030002 -#define SYS_CALL_PROC_REG_SIG 0x030003 -#define SYS_CALL_PROC_GETPID 0x030004 -#define SYS_CALL_PROC_QUEUE_EVENT 0x030005 -#define SYS_CALL_PROC_YIELD 0x030006 -#define SYS_CALL_PROC_EXEC 0x030007 -#define SYS_CALL_PROC_SET_FOREGROUND 0x030008 +#define SYS_CALL_IO_OPEN ((SYS_CALL_FAMILY_IO << 16) | 0x0001) +#define SYS_CALL_IO_CLOSE ((SYS_CALL_FAMILY_IO << 16) | 0x0002) +#define SYS_CALL_IO_READ ((SYS_CALL_FAMILY_IO << 16) | 0x0003) +#define SYS_CALL_IO_WRITE ((SYS_CALL_FAMILY_IO << 16) | 0x0004) +#define SYS_CALL_IO_SIZE ((SYS_CALL_FAMILY_IO << 16) | 0x0005) + +#define SYS_CALL_MEM_MALLOC ((SYS_CALL_FAMILY_MEM << 16) | 0x0001) +#define SYS_CALL_MEM_REALLOC ((SYS_CALL_FAMILY_MEM << 16) | 0x0002) +#define SYS_CALL_MEM_FREE ((SYS_CALL_FAMILY_MEM << 16) | 0x0003) + +#define SYS_CALL_PROC_EXIT ((SYS_CALL_FAMILY_PROC << 16) | 0x0001) +#define SYS_CALL_PROC_ABORT ((SYS_CALL_FAMILY_PROC << 16) | 0x0002) +#define SYS_CALL_PROC_PANIC ((SYS_CALL_FAMILY_PROC << 16) | 0x0003) +#define SYS_CALL_PROC_REG_SIG ((SYS_CALL_FAMILY_PROC << 16) | 0x0004) +#define SYS_CALL_PROC_GETPID ((SYS_CALL_FAMILY_PROC << 16) | 0x0005) +#define SYS_CALL_PROC_QUEUE_EVENT ((SYS_CALL_FAMILY_PROC << 16) | 0x0006) +#define SYS_CALL_PROC_YIELD ((SYS_CALL_FAMILY_PROC << 16) | 0x0007) +#define SYS_CALL_PROC_EXEC ((SYS_CALL_FAMILY_PROC << 16) | 0x0008) +#define SYS_CALL_PROC_SET_FOREGROUND ((SYS_CALL_FAMILY_PROC << 16) | 0x0009) #define SYS_CALL_PROC_LIST_OPEN #define SYS_CALL_PROC_LIST_CLOSE From 02e7380fd6c2966b7d7c1bd600c8576ad4a96931 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 15 Mar 2026 11:58:12 -0400 Subject: [PATCH 28/38] Document ring scheduler --- design/process.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/design/process.md b/design/process.md index 19cfdd8..d96fa25 100644 --- a/design/process.md +++ b/design/process.md @@ -51,6 +51,38 @@ the process page dir does not include a stack for the kernel (eg. isr stack). TODO : parent pid +## Ring Scheduler + +There needs to be some intermediate task scheduler until a more complete one is +implemented (similar to how malloc needed an intermediate). This intermediate +scheduler will be a ring scheduler. + +Each process is in a linked list with a pointer to the next process (and +previous for list removal). When a task switch is performed, the next process +in checked for fulfillment of the event filter. This is repeated until a ready +to run task is found. + +> [!WARNING] There must be at least one process ready to run +> +> There must always be a "next" task ready to run. In the case where the current +> process is yielding with an event filter, another process must be ready to +> launch. This will most likely be init, so there needs to be some documentation +> for init behavior written which includes that it must never yield with an +> event filter. + +### Process Manager + +has pointer to first and foreground processes + +### Searching for PID + +starts at foreground task + +### Event Filter Fulfillment + +When the task filter is 0 or there is an event with matching id to filter type. + + # Old ## Memory From 792bc11368c0c8b2979d35f7cf0e745eab16677c Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 15 Mar 2026 11:58:46 -0400 Subject: [PATCH 29/38] Add event sys call family --- src/kernel/include/kernel/system_call_event.h | 8 +++ src/kernel/src/kernel.c | 2 + src/kernel/src/kernel/system_call_event.c | 62 +++++++++++++++++++ src/libk/include/libk/defs.h | 4 ++ 4 files changed, 76 insertions(+) create mode 100644 src/kernel/include/kernel/system_call_event.h create mode 100644 src/kernel/src/kernel/system_call_event.c diff --git a/src/kernel/include/kernel/system_call_event.h b/src/kernel/include/kernel/system_call_event.h new file mode 100644 index 0000000..9cd2f31 --- /dev/null +++ b/src/kernel/include/kernel/system_call_event.h @@ -0,0 +1,8 @@ +#ifndef KERNEL_SYSTEM_CALL_EVENT_H +#define KERNEL_SYSTEM_CALL_EVENT_H + +#include "system_call.h" + +int sys_call_event_cb(uint32_t call_id, void * args_data, registers_t * regs); + +#endif // KERNEL_SYSTEM_CALL_EVENT_H diff --git a/src/kernel/src/kernel.c b/src/kernel/src/kernel.c index 1f988c5..4c2ff78 100644 --- a/src/kernel/src/kernel.c +++ b/src/kernel/src/kernel.c @@ -16,6 +16,7 @@ #include "exec.h" #include "kernel/logs.h" #include "kernel/panic.h" +#include "kernel/system_call_event.h" #include "kernel/system_call_io.h" #include "kernel/system_call_mem.h" #include "kernel/system_call_proc.h" @@ -104,6 +105,7 @@ static void setup_system_calls() { system_call_register(SYS_CALL_FAMILY_IO, sys_call_io_cb); system_call_register(SYS_CALL_FAMILY_MEM, sys_call_mem_cb); system_call_register(SYS_CALL_FAMILY_PROC, sys_call_proc_cb); + system_call_register(SYS_CALL_FAMILY_EVENT, sys_call_event_cb); } int kernel_exec(const char * filename, size_t argc, char ** argv) { diff --git a/src/kernel/src/kernel/system_call_event.c b/src/kernel/src/kernel/system_call_event.c new file mode 100644 index 0000000..94552b4 --- /dev/null +++ b/src/kernel/src/kernel/system_call_event.c @@ -0,0 +1,62 @@ +#define KLOG_SERVICE "SYSCALL/EVENT" + +#include "kernel/system_call_event.h" + +#include + +#include "defs.h" +#include "drivers/vga.h" +#include "ebus.h" +#include "exec.h" +#include "kernel.h" +#include "kernel/logs.h" +#include "libc/proc.h" +#include "libc/stdio.h" +#include "libc/string.h" +#include "libk/defs.h" +#include "process.h" + +int sys_call_event_cb(uint32_t call_id, void * args_data, registers_t * regs) { + process_t * proc = get_current_process(); + + KLOG_TRACE("Call id 0x%X from pid %u", call_id, proc->pid); + + switch (call_id) { + default: { + KLOG_WARNING("Invalid call id 0x%X", call_id); + break; + } + + // Generic event pull, make another case block for more specific logic + case SYS_CALL_EVENT_PULL: { + struct _args { + int filter; + ebus_event_t * event_out; + } * args = (struct _args *)args_data; + + proc->next_event.event_id = 0; + proc->filter_event.event_id = args->filter; + proc->state = PROCESS_STATE_WAITING; + + enable_interrupts(); + process_t * next = pm_get_next(kernel_get_proc_man()); + KLOG_DEBUG("Switching from process %u to %u", proc->pid, next->pid); + if (pm_resume_process(kernel_get_proc_man(), next->pid)) { + KPANIC("Failed to resume process"); + } + + if (next->next_event.event_id != next->filter_event.event_id != args->filter) { + KPANIC("Tried to resume process but the event does not match filter"); + } + if (args->event_out) { + // TODO log + kmemcpy(&next->next_event, args->event_out, sizeof(ebus_event_t)); + } + + next->filter_event.event_id = 0; + next->next_event.event_id = 0; + } break; + } + + return 0; +} diff --git a/src/libk/include/libk/defs.h b/src/libk/include/libk/defs.h index 05b936e..90610e8 100644 --- a/src/libk/include/libk/defs.h +++ b/src/libk/include/libk/defs.h @@ -4,6 +4,7 @@ #define SYS_CALL_FAMILY_IO 0x01 #define SYS_CALL_FAMILY_MEM 0x02 #define SYS_CALL_FAMILY_PROC 0x03 +#define SYS_CALL_FAMILY_EVENT 0x04 #define SYS_CALL_FAMILY_STDIO 0x10 #define SYS_CALL_FAMILY_IO_FILE 0x11 #define SYS_CALL_FAMILY_IO_DIR 0x12 @@ -33,6 +34,9 @@ #define SYS_CALL_PROC_LIST_READ #define SYS_CALL_PROC_LIST_ +#define SYS_CALL_EVENT_KEY ((SYS_CALL_FAMILY_EVENT << 16) | 0x0001) +#define SYS_CALL_EVENT_PULL ((SYS_CALL_FAMILY_EVENT << 16) | 0x0002) + // #define SYS_CALL_STDIO_PUTC 0x1000 // #define SYS_CALL_STDIO_PUTS 0x1001 From 698a4bebb8daa5edd596594ebd9ced0a3c00f9aa Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Sun, 15 Mar 2026 11:59:29 -0400 Subject: [PATCH 30/38] Use ebus_event_t for filter_event, split _sys_yield into _sys_event_pull, remove args of _sys_yield --- src/kernel/include/process.h | 4 ++-- src/libc/src/proc.c | 4 ++-- src/libk/include/libk/sys_call.h | 4 +++- src/libk/src/sys_call.c | 8 ++++++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 57d3314..d40c17b 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -87,8 +87,8 @@ typedef struct _process { memory_t memory; /// Event type being waited on by process if state is PROCESS_STATE_WAITING - uint32_t filter_event; - /// Event matching filter_event if one is ready + ebus_event_t filter_event; + /// Event matching filter_event if one is ready ebus_event_t next_event; /// Current state of process (eg. loading, running, waiting, dead, etc.) enum PROCESS_STATE state; diff --git a/src/libc/src/proc.c b/src/libc/src/proc.c index 935fd90..9a6b155 100644 --- a/src/libc/src/proc.c +++ b/src/libc/src/proc.c @@ -21,11 +21,11 @@ void queue_event(ebus_event_t * event) { } int pull_event(int filter, ebus_event_t * event_out) { - return _sys_yield(filter, event_out); + return _sys_event_pull(filter, event_out); } void yield() { - _sys_yield(0, 0); + _sys_yield(); } int proc_open(const char * filename, size_t argc, char ** argv) { diff --git a/src/libk/include/libk/sys_call.h b/src/libk/include/libk/sys_call.h index 9abef2e..c766686 100644 --- a/src/libk/include/libk/sys_call.h +++ b/src/libk/include/libk/sys_call.h @@ -33,7 +33,9 @@ int _sys_proc_getpid(void); void _sys_register_signals(void * callback); void _sys_queue_event(ebus_event_t * event); -int _sys_yield(int filter, ebus_event_t * event_out); +void _sys_yield(void); int _sys_proc_set_foreground(int pid); +int _sys_event_pull(int filter, ebus_event_t * event_out); + #endif // LIBK_SYS_CALL_H diff --git a/src/libk/src/sys_call.c b/src/libk/src/sys_call.c index 0fcd231..563548d 100644 --- a/src/libk/src/sys_call.c +++ b/src/libk/src/sys_call.c @@ -70,8 +70,8 @@ void _sys_queue_event(ebus_event_t * event) { send_call(SYS_CALL_PROC_QUEUE_EVENT, event); } -int _sys_yield(int filter, ebus_event_t * event_out) { - return send_call(SYS_CALL_PROC_YIELD, filter, event_out); +void _sys_yield() { + send_call(SYS_CALL_PROC_YIELD); } int _sys_proc_exec(const char * filename, int argc, char ** argv) { @@ -81,3 +81,7 @@ int _sys_proc_exec(const char * filename, int argc, char ** argv) { int _sys_proc_set_foreground(int pid) { return send_call(SYS_CALL_PROC_SET_FOREGROUND, pid); } + +int _sys_event_pull(int filter, ebus_event_t * event_out) { + return send_call(SYS_CALL_EVENT_PULL); +} From 6c57a26d0dd30870b1e8bcbb26afbe50072827ad Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 16 Mar 2026 03:14:29 -0400 Subject: [PATCH 31/38] Add getpid app --- src/apps/CMakeLists.txt | 1 + src/apps/getpid/CMakeLists.txt | 3 +++ src/apps/getpid/link.ld | 29 +++++++++++++++++++++++++++++ src/apps/getpid/src/getpid.c | 7 +++++++ 4 files changed, 40 insertions(+) create mode 100644 src/apps/getpid/CMakeLists.txt create mode 100644 src/apps/getpid/link.ld create mode 100644 src/apps/getpid/src/getpid.c diff --git a/src/apps/CMakeLists.txt b/src/apps/CMakeLists.txt index a0c0df1..4cf9f76 100644 --- a/src/apps/CMakeLists.txt +++ b/src/apps/CMakeLists.txt @@ -25,6 +25,7 @@ add_subdirectory(demo) add_subdirectory(ping) add_subdirectory(pong) add_subdirectory(shell) +add_subdirectory(getpid) message("App targets are ${APPS_TARGETS}") diff --git a/src/apps/getpid/CMakeLists.txt b/src/apps/getpid/CMakeLists.txt new file mode 100644 index 0000000..444d0d0 --- /dev/null +++ b/src/apps/getpid/CMakeLists.txt @@ -0,0 +1,3 @@ +set(TARGET getpid) + +add_app(${TARGET}) diff --git a/src/apps/getpid/link.ld b/src/apps/getpid/link.ld new file mode 100644 index 0000000..9ac34e3 --- /dev/null +++ b/src/apps/getpid/link.ld @@ -0,0 +1,29 @@ +ENTRY(__start) + +SECTIONS { + . = 0x400000; + + .text : + { + *(.text) + } + + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } +} \ No newline at end of file diff --git a/src/apps/getpid/src/getpid.c b/src/apps/getpid/src/getpid.c new file mode 100644 index 0000000..2c6f367 --- /dev/null +++ b/src/apps/getpid/src/getpid.c @@ -0,0 +1,7 @@ +#include "libc/proc.h" +#include "libc/stdio.h" + +void __start() { + int pid = getpid(); + printf("PID is %u\n"); +} From 25b77bc3ec911b013f6e5afb8a5b9bbc59dc9457 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 16 Mar 2026 03:16:04 -0400 Subject: [PATCH 32/38] Remove event type check in shell app --- src/apps/shell/src/shell.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/apps/shell/src/shell.c b/src/apps/shell/src/shell.c index 02c3965..9c435e4 100644 --- a/src/apps/shell/src/shell.c +++ b/src/apps/shell/src/shell.c @@ -199,19 +199,17 @@ void term_run() { for (;;) { ebus_event_t event; if (pull_event(EBUS_EVENT_KEY, &event)) { - // printf("Got event type 0x%04x\n", event.event_id); - if (event.event_id == EBUS_EVENT_KEY) { - key_cb(event.key.keycode, event.key.c, event.key.event, event.key.mods); - // printf("Got key %c %x %x\n", event.key.c, event.key.keycode, event.key.scancode); - // if (event.key.event == 0) { - // putc(event.key.c); - // } - - // char c = getc(); - // if (c) { - // key_char_cb(c); - // } - } + // printf("Got event type 0x%04x located at %p\n", event.event_id, &event); + key_cb(event.key.keycode, event.key.c, event.key.event, event.key.mods); + // printf("Got key %c keycode 0x%x scancode 0x%x location %p\n", event.key.c, event.key.keycode, event.key.scancode, &event); + // if (event.key.event == 0) { + // putc(event.key.c); + // } + + // char c = getc(); + // if (c) { + // key_char_cb(c); + // } } term_update(); } From c17586c44778b6fc45c4fc569667d949de6cd5f1 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 16 Mar 2026 03:26:32 -0400 Subject: [PATCH 33/38] Fix task switching with ring scheduler --- src/apps/shell/src/shell.c | 2 +- src/kernel/include/kernel.h | 2 - src/kernel/src/kernel/system_call_event.c | 19 ++++-- src/kernel/src/process_manager.c | 83 +++++++++++++++-------- src/libk/src/sys_call.c | 2 +- 5 files changed, 70 insertions(+), 38 deletions(-) diff --git a/src/apps/shell/src/shell.c b/src/apps/shell/src/shell.c index 9c435e4..73cc24f 100644 --- a/src/apps/shell/src/shell.c +++ b/src/apps/shell/src/shell.c @@ -198,7 +198,7 @@ void term_run() { for (;;) { ebus_event_t event; - if (pull_event(EBUS_EVENT_KEY, &event)) { + if (!pull_event(EBUS_EVENT_KEY, &event)) { // printf("Got event type 0x%04x located at %p\n", event.event_id, &event); key_cb(event.key.keycode, event.key.c, event.key.event, event.key.mods); // printf("Got key %c keycode 0x%x scancode 0x%x location %p\n", event.key.c, event.key.keycode, event.key.scancode, &event); diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h index 0e6ef59..5b74647 100644 --- a/src/kernel/include/kernel.h +++ b/src/kernel/include/kernel.h @@ -46,8 +46,6 @@ void tmp_register_signals_cb(signals_master_cb_t cb); void kernel_queue_event(ebus_event_t * event); -// ebus_event_t * pull_event(int event_id); - typedef int (*_proc_call_t)(void * data); int kernel_call_as_proc(int pid, _proc_call_t fn, void * data); diff --git a/src/kernel/src/kernel/system_call_event.c b/src/kernel/src/kernel/system_call_event.c index 94552b4..24238f9 100644 --- a/src/kernel/src/kernel/system_call_event.c +++ b/src/kernel/src/kernel/system_call_event.c @@ -1,4 +1,5 @@ #define KLOG_SERVICE "SYSCALL/EVENT" +// #define KLOG_LEVEL KERNEL_LOG_LEVEL_TRACE #include "kernel/system_call_event.h" @@ -34,27 +35,33 @@ int sys_call_event_cb(uint32_t call_id, void * args_data, registers_t * regs) { ebus_event_t * event_out; } * args = (struct _args *)args_data; + if (!args->filter) { + KLOG_WARNING("Event pul system call with no filter"); + return 1; + } + proc->next_event.event_id = 0; proc->filter_event.event_id = args->filter; proc->state = PROCESS_STATE_WAITING; enable_interrupts(); process_t * next = pm_get_next(kernel_get_proc_man()); - KLOG_DEBUG("Switching from process %u to %u", proc->pid, next->pid); if (pm_resume_process(kernel_get_proc_man(), next->pid)) { KPANIC("Failed to resume process"); } - if (next->next_event.event_id != next->filter_event.event_id != args->filter) { + proc = get_current_process(); + + // args->filter doesn't appear to be valid here, why not? + if (!(proc->next_event.event_id == proc->filter_event.event_id)) { KPANIC("Tried to resume process but the event does not match filter"); } if (args->event_out) { - // TODO log - kmemcpy(&next->next_event, args->event_out, sizeof(ebus_event_t)); + kmemcpy(args->event_out, &proc->next_event, sizeof(ebus_event_t)); } - next->filter_event.event_id = 0; - next->next_event.event_id = 0; + proc->filter_event.event_id = 0; + proc->next_event.event_id = 0; } break; } diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 4217b30..7f4bf13 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -1,4 +1,5 @@ #define KLOG_SERVICE "KERNEL/PROCESS_MANAGER" +// #define KLOG_LEVEL KLOG_LEVEL_TRACE #include "process_manager.h" @@ -38,24 +39,21 @@ process_t * pm_find_pid(proc_man_t * pm, int pid) { } if (pm->foreground_task && pm->foreground_task->pid == pid) { - KLOG_TRACE("Returning foreground task for pid %u", pid); return pm->foreground_task; } process_t * proc = pm->first_task; if (proc->pid == pid) { - KLOG_TRACE("Returning first task for pid %u", pid); return proc; } - proc = proc->next; - while (proc != pm->first_task) { + do { if (proc->pid == pid) { return proc; } proc = proc->next; - } + } while (proc != pm->first_task); return 0; } @@ -80,17 +78,27 @@ int pm_add_proc(proc_man_t * pm, process_t * proc) { proc->prev = proc; return 0; } - else if (pm->first_task->next == pm->first_task) { - KLOG_DEBUG("Assigning second process to be %u", proc->pid); - pm->first_task->next = proc; - pm->first_task->prev = proc; - proc->next = pm->first_task; - proc->prev = pm->first_task; + if (pm_find_pid(pm, proc->pid)) { + KLOG_WARNING("Tried to add process %u to manager, already added", proc->pid); + return 0; } - KLOG_DEBUG("Linking last task %u to new process %u", proc->prev->pid, proc->pid); - return process_link(proc->prev, proc); + process_t * prev = pm->first_task->prev; + KLOG_TRACE("Using process %u as previous to first task %u", prev->pid, pm->first_task->pid); + + prev->next = proc; + pm->first_task->prev = proc; + + proc->next = pm->first_task; + proc->prev = prev; + + process_t * p = pm->first_task; + do { + KLOG_TRACE("Link %u n %u p %u", p->pid, p->next->pid, p->prev->pid); + p = p->next; + } while (p != pm->first_task); + return 0; } int pm_remove_proc(proc_man_t * pm, int pid) { @@ -183,21 +191,35 @@ process_t * pm_get_next(proc_man_t * pm) { process_t * proc = pm->foreground_task->next; - while (proc != pm->foreground_task) { + // KLOG_TRACE("Start looking for next process"); + + do { + // KLOG_TRACE("Looking at pid %u in state %u to see if it's ready", proc->pid, proc->state); + if (PROCESS_STATE_LOADED <= proc->state <= PROCESS_STATE_DEAD) { + if (!proc->filter_event.event_id) { + // KLOG_TRACE("Process %u has no filter event, so it's ready", proc->pid); + return proc; + } + // This handles the above case but is split for trace log if (proc->filter_event.event_id == proc->next_event.event_id) { + KLOG_TRACE("Process %u has ready event %u", proc->pid, proc->next_event.event_id); return proc; } + // KLOG_TRACE("Process %u is not ready, waiting for %u", proc->pid, proc->filter_event.event_id); } else { - KLOG_TRACE("Process with pid %u is not alive", proc->pid); + // KLOG_TRACE("Process with pid %u is not alive", proc->pid); } + // KLOG_TRACE("Going to next process %u, fg is %u", proc->next->pid, pm->foreground_task->pid); proc = proc->next; - }; + } while (proc != pm->foreground_task->next); + + // KLOG_TRACE("Finish looking for next process"); if (PROCESS_STATE_LOADED <= proc->state <= PROCESS_STATE_DEAD) { - KLOG_TRACE("Next process is the foreground process with pid %u", proc->pid); + // KLOG_TRACE("Next process is the foreground process with pid %u", proc->pid); return proc; } @@ -218,30 +240,35 @@ int pm_push_event(proc_man_t * pm, ebus_event_t * event) { return -1; } - if (pm->first_task->filter_event.event_id == event->event_id) { - if (!pm->first_task->next_event.event_id) { - KLOG_WARNING("Replacing event %u with %u for process %u", pm->first_task->next_event.event_id, event->event_id, pm->first_task->pid); - } - kmemcpy(event, &pm->first_task->next_event, sizeof(ebus_event_t)); - } + KLOG_TRACE("Start push event %u", event->event_id); - process_t * proc = pm->first_task->next; + process_t * proc = pm->first_task; - while (proc != pm->first_task) { + do { if (proc->filter_event.event_id == event->event_id) { - if (!proc->next_event.event_id) { + KLOG_TRACE("Push event %u to %u", event->event_id, proc->pid); + if (proc->next_event.event_id) { KLOG_WARNING("Replacing event %u with %u for process %u", proc->next_event.event_id, event->event_id, proc->pid); } - kmemcpy(event, &proc->next_event, sizeof(ebus_event_t)); + kmemcpy(&proc->next_event, event, sizeof(ebus_event_t)); + + if (event->event_id == EBUS_EVENT_KEY) { + KLOG_TRACE("Push scancode 0x%x results in 0x%x", event->key.scancode, proc->next_event.key.scancode); + } if (proc->state == PROCESS_STATE_WAITING) { KLOG_TRACE("Setting process state to suspended for pid %u", proc->pid); proc->state = PROCESS_STATE_SUSPENDED; } } + else { + KLOG_TRACE("Event %u did not match pid %u waiting on %u", event->event_id, proc->pid, proc->filter_event.event_id); + } proc = proc->next; - } + } while (proc != pm->first_task); + + KLOG_TRACE("Finish push event %u", event->event_id); return 0; } diff --git a/src/libk/src/sys_call.c b/src/libk/src/sys_call.c index 563548d..9e9367f 100644 --- a/src/libk/src/sys_call.c +++ b/src/libk/src/sys_call.c @@ -83,5 +83,5 @@ int _sys_proc_set_foreground(int pid) { } int _sys_event_pull(int filter, ebus_event_t * event_out) { - return send_call(SYS_CALL_EVENT_PULL); + return send_call(SYS_CALL_EVENT_PULL, filter, event_out); } From d5d2d2a820984ca31605cb5bd7c96f96e51e72b2 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 16 Mar 2026 04:19:55 -0400 Subject: [PATCH 34/38] Add time_start_timer_us, fix timer with 0 ticks --- src/kernel/include/kernel/time.h | 1 + src/kernel/src/kernel/time.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/kernel/include/kernel/time.h b/src/kernel/include/kernel/time.h index a8bad03..0696a21 100644 --- a/src/kernel/include/kernel/time.h +++ b/src/kernel/include/kernel/time.h @@ -19,6 +19,7 @@ void time_init(uint32_t freq); */ int time_start_timer(uint32_t ticks); int time_start_timer_ns(uint32_t ns); +int time_start_timer_us(uint32_t us); int time_start_timer_ms(uint32_t ms); void time_stop_timer(int id); diff --git a/src/kernel/src/kernel/time.c b/src/kernel/src/kernel/time.c index a62142f..931c57f 100644 --- a/src/kernel/src/kernel/time.c +++ b/src/kernel/src/kernel/time.c @@ -72,12 +72,16 @@ void time_init(uint32_t freq) { } int time_start_timer(uint32_t ticks) { + if (!ticks) { + KLOG_TRACE("Tried to start a timer of 0 ticks"); + return 0; + } timer_t t; t.id = __next_id++; t.count = ticks; if (arr_insert(&__timers, arr_size(&__timers), &t)) { KLOG_ERROR("Failed to insert into timers array"); - return -1; + return 0; } KLOG_DEBUG("Starting timer %d of %u ticks", t.id, t.count); return t.id; @@ -87,6 +91,10 @@ int time_start_timer_ns(uint32_t ns) { return time_start_timer(ns * __freq / 1000000000); } +int time_start_timer_us(uint32_t us) { + return time_start_timer(us * __freq / 1000000); +} + int time_start_timer_ms(uint32_t ms) { return time_start_timer(ms * __freq / 1000); } From ac708e34641046c87c10d7b1afe6d1eee5aa5276 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 16 Mar 2026 04:20:37 -0400 Subject: [PATCH 35/38] Add system call for time and sleep --- src/kernel/src/kernel/system_call_event.c | 51 ++++++++++++++++++++++- src/libk/include/libk/defs.h | 5 ++- src/libk/include/libk/sys_call.h | 3 ++ src/libk/src/sys_call.c | 8 ++++ 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/kernel/src/kernel/system_call_event.c b/src/kernel/src/kernel/system_call_event.c index 24238f9..4a105dd 100644 --- a/src/kernel/src/kernel/system_call_event.c +++ b/src/kernel/src/kernel/system_call_event.c @@ -11,6 +11,7 @@ #include "exec.h" #include "kernel.h" #include "kernel/logs.h" +#include "kernel/time.h" #include "libc/proc.h" #include "libc/stdio.h" #include "libc/string.h" @@ -50,8 +51,6 @@ int sys_call_event_cb(uint32_t call_id, void * args_data, registers_t * regs) { KPANIC("Failed to resume process"); } - proc = get_current_process(); - // args->filter doesn't appear to be valid here, why not? if (!(proc->next_event.event_id == proc->filter_event.event_id)) { KPANIC("Tried to resume process but the event does not match filter"); @@ -63,6 +62,54 @@ int sys_call_event_cb(uint32_t call_id, void * args_data, registers_t * regs) { proc->filter_event.event_id = 0; proc->next_event.event_id = 0; } break; + + case SYS_CALL_EVENT_TIME: { + enable_interrupts(); + process_t * next = pm_get_next(kernel_get_proc_man()); + if (pm_resume_process(kernel_get_proc_man(), next->pid)) { + KPANIC("Failed to resume process"); + } + + return time_s(); + } break; + + case SYS_CALL_EVENT_SLEEP: { + struct _args { + size_t ms; + size_t us; + } * args = (struct _args *)args_data; + + int timer_id = 0; + if (args->ms) { + KLOG_TRACE("Using millisecond sleep %u", args->ms); + timer_id = time_start_timer_ms(args->ms); + } + else { + KLOG_TRACE("Using microsecond sleep %u", args->us); + timer_id = time_start_timer_us(args->us); + } + + if (timer_id < 1) { + KLOG_WARNING("Failed to start timer of %u ms\n", args->ms); + return 1; + } + + proc->next_event.event_id = 0; + proc->next_event.timer.id = 0; + proc->next_event.timer.time = 0; + proc->filter_event.event_id = EBUS_EVENT_TIMER; + proc->filter_event.timer.id = timer_id; + proc->state = PROCESS_STATE_WAITING; + + do { + enable_interrupts(); + process_t * next = pm_get_next(kernel_get_proc_man()); + if (pm_resume_process(kernel_get_proc_man(), next->pid)) { + KPANIC("Failed to resume process"); + } + KLOG_TRACE("Back from timer %u", timer_id); + } while (proc->next_event.timer.id != timer_id); + } break; } return 0; diff --git a/src/libk/include/libk/defs.h b/src/libk/include/libk/defs.h index 90610e8..5feabd9 100644 --- a/src/libk/include/libk/defs.h +++ b/src/libk/include/libk/defs.h @@ -34,8 +34,9 @@ #define SYS_CALL_PROC_LIST_READ #define SYS_CALL_PROC_LIST_ -#define SYS_CALL_EVENT_KEY ((SYS_CALL_FAMILY_EVENT << 16) | 0x0001) -#define SYS_CALL_EVENT_PULL ((SYS_CALL_FAMILY_EVENT << 16) | 0x0002) +#define SYS_CALL_EVENT_PULL ((SYS_CALL_FAMILY_EVENT << 16) | 0x0001) +#define SYS_CALL_EVENT_TIME ((SYS_CALL_FAMILY_EVENT << 16) | 0x0002) +#define SYS_CALL_EVENT_SLEEP ((SYS_CALL_FAMILY_EVENT << 16) | 0x0003) // #define SYS_CALL_STDIO_PUTC 0x1000 // #define SYS_CALL_STDIO_PUTS 0x1001 diff --git a/src/libk/include/libk/sys_call.h b/src/libk/include/libk/sys_call.h index c766686..bafeafb 100644 --- a/src/libk/include/libk/sys_call.h +++ b/src/libk/include/libk/sys_call.h @@ -38,4 +38,7 @@ int _sys_proc_set_foreground(int pid); int _sys_event_pull(int filter, ebus_event_t * event_out); +size_t _sys_event_time(void); +void _sys_event_sleep(size_t ms, size_t us); + #endif // LIBK_SYS_CALL_H diff --git a/src/libk/src/sys_call.c b/src/libk/src/sys_call.c index 9e9367f..68d1c65 100644 --- a/src/libk/src/sys_call.c +++ b/src/libk/src/sys_call.c @@ -85,3 +85,11 @@ int _sys_proc_set_foreground(int pid) { int _sys_event_pull(int filter, ebus_event_t * event_out) { return send_call(SYS_CALL_EVENT_PULL, filter, event_out); } + +size_t _sys_event_time() { + return send_call(SYS_CALL_EVENT_TIME); +} + +void _sys_event_sleep(size_t ms, size_t us) { + send_call(SYS_CALL_EVENT_SLEEP, ms, us); +} From 361f756c5c5bd69865d601fadbc8f8f8c631aa42 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 16 Mar 2026 04:21:40 -0400 Subject: [PATCH 36/38] Add time.h to libc --- src/libc/include/libc/time.h | 10 ++++++++++ src/libc/src/time.c | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/libc/include/libc/time.h create mode 100644 src/libc/src/time.c diff --git a/src/libc/include/libc/time.h b/src/libc/include/libc/time.h new file mode 100644 index 0000000..c0c54d3 --- /dev/null +++ b/src/libc/include/libc/time.h @@ -0,0 +1,10 @@ +#ifndef LIBC_TIME_H +#define LIBC_TIME_H + +#include + +size_t time(void); +void sleep(size_t ms); +void usleep(size_t us); + +#endif // LIBC_TIME_H diff --git a/src/libc/src/time.c b/src/libc/src/time.c new file mode 100644 index 0000000..7980317 --- /dev/null +++ b/src/libc/src/time.c @@ -0,0 +1,16 @@ +#include "libc/time.h" + +#include "ebus.h" +#include "libk/sys_call.h" + +size_t time() { + return _sys_event_time(); +} + +void sleep(size_t ms) { + _sys_event_sleep(ms, 0); +} + +void usleep(size_t us) { + _sys_event_sleep(0, us); +} From 3830fe95f5a2ae4ececf4d43d8b6202e989c15b9 Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 16 Mar 2026 04:22:19 -0400 Subject: [PATCH 37/38] Add sleep and time commands --- src/apps/shell/src/commands.c | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/apps/shell/src/commands.c b/src/apps/shell/src/commands.c index 4dcd512..71d63f3 100644 --- a/src/apps/shell/src/commands.c +++ b/src/apps/shell/src/commands.c @@ -5,6 +5,7 @@ #include "libc/proc.h" #include "libc/stdio.h" #include "libc/string.h" +#include "libc/time.h" #include "shell.h" static int echo_cmd(size_t argc, char ** argv) { @@ -86,9 +87,51 @@ static int pid_cmd(size_t argc, char ** argv) { return 0; } +static int sleep_cmd(size_t argc, char ** argv) { + if (argc < 2 || (!kstrcmp(argv[1], "-u") && argc < 3)) { + printf("Usage: %s [-u] \n", argv[0]); + puts("\nseconds must be at while number that is least 1\n"); + puts("-u use microseconds instead of seconds\n"); + return -1; + } + + if (!kstrcmp(argv[1], "-u")) { + int us = katoi(argv[2]); + if (us < 1) { + printf("Seconds must be a numer that is at least 1\n"); + return -1; + } + + printf("Sleeping for %d microseconds\n", us); + usleep(us); + } + else { + int seconds = katoi(argv[1]); + if (seconds < 1) { + printf("Seconds must be a numer that is at least 1\n"); + return -1; + } + + printf("Sleeping for %d sseconds\n", seconds); + sleep(seconds * 1000); + } + + puts("Finished sleep\n"); + + return 0; +} + +static int time_cmd(size_t argc, char ** argv) { + printf("The time is %u seconds\n", time()); + + return 0; +} + void init_commands() { term_command_add("echo", echo_cmd); term_command_add("ls", ls_cmd); term_command_add("cat", cat_cmd); term_command_add("pid", pid_cmd); + term_command_add("sleep", sleep_cmd); + term_command_add("time", time_cmd); } From c39142261bbf06ab7e199443ed30d5ae3ad5434d Mon Sep 17 00:00:00 2001 From: Thomas Harrison Date: Mon, 16 Mar 2026 04:38:01 -0400 Subject: [PATCH 38/38] Fix tests build --- tests/src/mocks/include/libk/sys_call.mock.h | 2 +- tests/src/mocks/src/libk.mock.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/mocks/include/libk/sys_call.mock.h b/tests/src/mocks/include/libk/sys_call.mock.h index 4dab349..ee2ed5b 100644 --- a/tests/src/mocks/include/libk/sys_call.mock.h +++ b/tests/src/mocks/include/libk/sys_call.mock.h @@ -14,7 +14,7 @@ DECLARE_FAKE_VOID_FUNC(_sys_proc_panic, const char *, const char *, unsigned int DECLARE_FAKE_VALUE_FUNC(int, _sys_proc_getpid); DECLARE_FAKE_VOID_FUNC(_sys_register_signals, void *); DECLARE_FAKE_VOID_FUNC(_sys_queue_event, ebus_event_t *); -DECLARE_FAKE_VALUE_FUNC(int, _sys_yield, int, ebus_event_t *); +DECLARE_FAKE_VOID_FUNC(_sys_yield); DECLARE_FAKE_VALUE_FUNC(size_t, _sys_putc, char); DECLARE_FAKE_VALUE_FUNC(size_t, _sys_puts, const char *); diff --git a/tests/src/mocks/src/libk.mock.c b/tests/src/mocks/src/libk.mock.c index d1f712d..5a1ff57 100644 --- a/tests/src/mocks/src/libk.mock.c +++ b/tests/src/mocks/src/libk.mock.c @@ -13,7 +13,7 @@ DEFINE_FAKE_VOID_FUNC(_sys_proc_panic, const char *, const char *, unsigned int) DEFINE_FAKE_VALUE_FUNC(int, _sys_proc_getpid); DEFINE_FAKE_VOID_FUNC(_sys_register_signals, void *); DEFINE_FAKE_VOID_FUNC(_sys_queue_event, ebus_event_t *); -DEFINE_FAKE_VALUE_FUNC(int, _sys_yield, int, ebus_event_t *); +DEFINE_FAKE_VOID_FUNC(_sys_yield); DEFINE_FAKE_VALUE_FUNC(size_t, _sys_putc, char); DEFINE_FAKE_VALUE_FUNC(size_t, _sys_puts, const char *);