commit 7b1f1314a4618908b79db56b86bae5c9306dc65f from: Onana Onana Xavier Manuel date: Wed Sep 16 03:02:03 2026 UTC Added contract to the entry of thread to annouce all resources allocated at load time as struct contract. commit - 7abd0aa7f90dfa1a7147252f69971b23d6a119c9 commit + 7b1f1314a4618908b79db56b86bae5c9306dc65f blob - 3d351992d333c0c5df49bc4885d6bcd0b4f97c92 blob + 6574b6b771e87848e935b310dd24595b5227bcd1 --- alpha/libc.c +++ alpha/libc.c @@ -6,29 +6,36 @@ void (*sys_send)(struct sysc *call) = (void (*)(struct void output(const u8 *msg) { - struct sysc_echo echo; - echo.sysc.type = SYSC_ECHO; - echo.type = SYSC_ECHO_STRING; - echo.msg = msg; - sys_send((struct sysc *)&echo); + struct sysc sysc; + sysc.type = SYSC_ECHO; + sysc.echo.cmd = SYSC_ECHO_STRING; + for (int i = 0; i < SYSC_ECHO_MSG_LEN; i++) { + sysc.echo.msg[i] = msg[i]; + if (msg[i] == '\0') + break; + + if (i == SYSC_ECHO_MSG_LEN - 1) + sysc.echo.msg[i] = '\0'; + } + sys_send(&sysc); } void outputi(u64 i) { - struct sysc_echo echo; - echo.sysc.type = SYSC_ECHO; - echo.type = SYSC_ECHO_INTEGER; - echo.number = i; - sys_send((struct sysc *)&echo); + struct sysc sysc; + sysc.type = SYSC_ECHO; + sysc.echo.cmd = SYSC_ECHO_INTEGER; + sysc.echo.number = i; + sys_send(&sysc); } void outputh(u64 i) { - struct sysc_echo echo; - echo.sysc.type = SYSC_ECHO; - echo.type = SYSC_ECHO_HEXADECIMAL; - echo.number = i; - sys_send((struct sysc *)&echo); + struct sysc sysc; + sysc.type = SYSC_ECHO; + sysc.echo.cmd = SYSC_ECHO_HEXADECIMAL; + sysc.echo.number = i; + sys_send(&sysc); } blob - aa80895e24f1195b07f322154bb5f0f0912a0cb0 blob + e3c44299d8e2701bebb331312b659d8ccf0b5a63 --- alpha/libc.h +++ alpha/libc.h @@ -2,6 +2,15 @@ #include "types.h" +// Resources given to a thread on initialization +struct contract { + u8 *memBlock; // This is guaranteed to be zero'd at entry point + u64 memSize; + + u8 *sharedBlock; // Guaranteed to be zero'd at entry point as well + u64 sharedCount; +}; + // If you come from Unix-like this is kinda // like print. @@ -10,3 +19,5 @@ void output(const u8 *); void outputi(u64); void outputh(u64); + +// Memory allocation blob - 8c5eb444d30483b9169d4472de388a9f08637b48 blob + 1a2e9694bafd83253434326ace1ffd76de2b7ae1 --- alpha/main.c +++ alpha/main.c @@ -35,23 +35,26 @@ alpha_main(struct mmap *km) for (;;); } + static struct task* task_new(void *entry) { - struct sysc_new_thread snt; + struct sysc sysc; - snt.sysc.type = SYSC_NEW_THREAD; - snt.entry = entry; + sysc.type = SYSC_NEW_THREAD; + sysc.new_thread.entry = entry; + sysc.new_thread.memsize = PAGE_SIZE; + sysc.new_thread.seats = 0; for (int i = 0; i < MAX_TASKS; i++) { if (tasks[i].assigned == 0) { - sys_send((struct sysc *)&snt); + sys_send(&sysc); - if (snt.retid == -1) + if (sysc.new_thread.ret_id == -1) break; tasks[i].assigned = 1; - tasks[i].thread = snt.retid; + tasks[i].thread = sysc.new_thread.ret_id; return &tasks[i]; } } blob - 626656de7372e28c8776f0e056d187d7fdb35b4d blob + f1d4f0c49a7a3c8123c165c16d1de3bc11dfb79d --- build.sh +++ build.sh @@ -6,7 +6,7 @@ set -e KERNEL_DIR=kernel OS_NAME=49.bin -INCS='-I common -I .' +INCS='-I common -I . -I alpha' # Root task cd alpha blob - cee74ed4f57f2cd2531915e4dc3972c890094c26 blob + 4bbea456c1fc5e1c47816117ea97cf496fac0d68 --- c449 +++ c449 @@ -73,7 +73,18 @@ main() In this example thread 1 `main` is not able to read thread 0 static `name` variable. +[ ENTRY POINT ] +In traditionnal C, the main function is the entry point. It allows +argc and argv. In c449 it is different. Because of how the language +is directly tied to the operating system. The entry point becomes. + +void main(struct contract *con, int argc, u8 *argv); + +Where con contains the data requested in the executable header for +the thread to manage. Each thread entry follows this syntax. + + [ C PREPROCESSOR ] There are minor differences within C449. #define keyword does not blob - 80dc8b3b55590067ed94ce974b03df157bb78893 blob + bb2f9923c7086b799d508df2928705ea6e57536a --- kernel/kmain.c +++ kernel/kmain.c @@ -29,7 +29,6 @@ kmain(struct kinfo *kinfo, u8 drive) } kprint("IDT configured!\n"); - syscall_init(); ammap = kmmap_init(kinfo); if (ammap == nil) { @@ -37,6 +36,7 @@ kmain(struct kinfo *kinfo, u8 drive) return; } + syscall_init(); kpic_setup(); kprint("Page tables configured!\n"); @@ -46,7 +46,8 @@ kmain(struct kinfo *kinfo, u8 drive) static void kloop(struct module *amodule, struct mmap *ammap) { - struct thread *athread = thread_create((void (*)(void))(u64)amodule->entry); + struct thread *athread = thread_create((void (*)(void))(u64)amodule->entry, nil); + athread->state = THREAD_RUNNING; if (athread == nil) kprint("Failed to create thread\n"); blob - 62195e7b1db99e5a7a72a440fefd5dd6630afab3 blob + 077a29ae933f75dc7207fb1a35d01863c1e87b4e --- kernel/kmmap.c +++ kernel/kmmap.c @@ -100,10 +100,10 @@ allocate_memory(u64 bytes) count++; if (count == pages) { - for (u64 f = start; f < start + pages; f++) + for (u64 f = start; f < start + pages; f++) { set_bitmap(f * PAGE_SIZE); + } - // kprint("Address: "); kprinth(vminfo.tables[start]); kprint("\n"); return (u64 *)(start * PAGE_SIZE); } } else { blob - 2aaa27bd3d0a50f812e72284bcf53e13aaaad651 blob + f6fa1af4a7b0b7ba0d65afb136dece90e87f1654 --- kernel/kthreads.c +++ kernel/kthreads.c @@ -3,6 +3,7 @@ #include "kmmap.h" #include "kdebug.h" #include "kthreads.h" +#include "libc.h" #define MAX_USER_THREADS 64 @@ -10,7 +11,7 @@ static struct thread uthreads[MAX_USER_THREADS]; struct thread *cthread; struct thread* -thread_create(void (*entry)(void)) +thread_create(void (*entry)(void), struct sysc_new_thread *nthread) { struct thread *thread = nil; u64 *sp, usp; @@ -30,12 +31,22 @@ thread_create(void (*entry)(void)) } thread->base = allocate_memory(PAGE_SIZE * 2); + thread->con->memBlock = nil; + thread->con->memSize = 0; if (thread->base == nil) { thread->assigned = 0; return nil; } + if (nthread != nil) { + thread->con->memBlock = (u8 *)allocate_memory(nthread->memsize); + thread->con->memSize = nthread->memsize; + + for (int i = 0; i < thread->con->memSize; i++) + thread->con->memBlock[i] = 0; + } + sp = (u64 *)((u8*)thread->base + PAGE_SIZE * 2); usp = (u64)sp; @@ -45,6 +56,7 @@ thread_create(void (*entry)(void)) *(--sp) = 0x08; // Kernel CS *(--sp) = (u64)entry; // RIP + *(--sp) = (u64)thread->con; // rdi, this is the struct contract passed *(--sp) = 0; // rbp *(--sp) = 0; // rbx *(--sp) = 0; // r12 @@ -58,6 +70,12 @@ thread_create(void (*entry)(void)) return thread; } +void +thread_delete(u64 threadid) +{ + struct thread uthreads[threadid]; +} + s64 thread_getuid(struct thread *th) { @@ -95,12 +113,12 @@ thread_next() s64 uid = cid; for (u64 count = 0; count < MAX_USER_THREADS; count++) { - uid = (uid + 1) % MAX_USER_THREADS; + uid = (uid + 1) % MAX_USER_THREADS; - struct thread *th = &uthreads[uid]; + struct thread *th = &uthreads[uid]; - if (th->assigned) - return th; + if (th->assigned && th->state == THREAD_RUNNING) + return th; } return nil; } blob - db7769a823069ca6a111484422253a3d2584125a blob + 19fbabd1b9e9124fcbbe564306ffed98b5414247 --- kernel/kthreads.h +++ kernel/kthreads.h @@ -1,6 +1,8 @@ #pragma once +#include "libc.h" #include "kmmap.h" +#include "syscalls/syscalls.h" enum thread_state { THREAD_READY, @@ -12,13 +14,15 @@ struct thread { u64 *top; u64 rsp; + struct contract *con; + u8 assigned; enum thread_state state; }; extern struct thread *cthread; -struct thread *thread_create(void (*entry)(void)); +struct thread *thread_create(void (*entry)(void), struct sysc_new_thread *); s64 thread_getuid(struct thread *th); void thread_schedule(struct mmap *, struct thread *); struct thread* thread_next(void); blob - 2dc35b1e0b56da7ebf126adaf33be290cd292dc7 blob + 9a2536142cad0000aaa41b994eea2d2b3c4328b7 --- kernel/lidt.s +++ kernel/lidt.s @@ -41,6 +41,7 @@ general_protection_handler: timer_handler: cli + push rdi push rbp push rbx push r12 @@ -68,6 +69,7 @@ timer_handler: pop r12 pop rbx pop rbp + pop rdi iretq blob - 014a9a1f363403a2edea51c96f40aa503e2abfb4 blob + 478f81a77d1f715eab260debc263446726aeda1f --- kernel/switch.s +++ kernel/switch.s @@ -5,14 +5,16 @@ global start_alpha start_alpha: + cli mov rsp, [rsi + RSP_OFFSET] + pop rdi pop r15 pop r14 pop r13 pop r12 pop rbx pop rbp - + iretq ; See kthread struct blob - ef4077ea1afc937475b103521f2bd6c238d74b47 blob + af6e2abed99462469afc6841fd8300cd54b9c97c --- kernel/syscalls.c +++ kernel/syscalls.c @@ -1,17 +1,34 @@ #include "types.h" +#include "kmmap.h" #include "kdebug.h" #include "kthreads.h" #include "syscalls/syscalls.h" -#define MAX_SEATS 64 +#define MAX_SEATS 256 +#define MAX_SYSC_QUEUE 64 +#define THREADID_NONE -1 struct seatmap { - u64 send; // Sender Thread - u64 recv; // Receiver Thread + s64 send; // Sender Thread + s64 recv; // Receiver Thread }; static struct seatmap seatmaps[MAX_SEATS]; +static u8 *sbuffers; +s8 +seat_new(u64 threadid) +{ + for (int i = 0; i < MAX_SEATS; i++) { + if (seatmaps[i].recv == THREADID_NONE) { + seatmaps[i].recv = threadid; + return 0; + } + } + + return -1; +} + void syscall_handler(struct sysc *); // Trampoline @@ -19,7 +36,19 @@ void syscall_init() { u8 *jump = (u8 *)SYSC_BELL; u64 addr = (u64)&syscall_handler; + sbuffers = (u8 *)allocate_memory(PAGE_SIZE * MAX_SEATS); + if (sbuffers == nil) { + kprint("Failed to create seat buffers!\n"); + repeat: + goto repeat; + } + + for (int i = 0; i < MAX_SEATS; i++) { + seatmaps[i].send = THREADID_NONE; + seatmaps[i].recv = THREADID_NONE; + } + // movabs rax, addr jump[0] = 0x48; jump[1] = 0xB8; @@ -31,9 +60,10 @@ void syscall_init() } void -syscall_echo_h(struct sysc_echo *echo) +syscall_echo_h(struct sysc *call) { - switch (echo->type) { + struct sysc_echo *echo = &call->echo; + switch (echo->cmd) { case SYSC_ECHO_STRING: kprint(echo->msg); break; @@ -48,17 +78,30 @@ syscall_echo_h(struct sysc_echo *echo) } } +// This functions creates a thread with all the resources it +// needs such as the amount of seats. If another thread wishes +// to connect to a specific thread it just does SYSC_CONNECT void -syscall_new_thread_h(struct sysc_new_thread *nthread) +syscall_new_thread_h(struct sysc *call) { - struct thread *th = thread_create(nthread->entry); + struct sysc_new_thread *nthread = &call->new_thread; + struct thread *th = thread_create(nthread->entry, nthread); s64 threadid; if (th == nil) kprint("failed to create thread from syscall!\n"); + /* + if (seat_new(threadid) == -1) { + kprint("Failed to create new seat\n"); + repeat: + goto repeat; + } + */ + threadid = thread_getuid(th); - nthread->retid = threadid; + nthread->ret_id = threadid; + th->state = THREAD_RUNNING; kprint("Thread (id="); kprinti(threadid); kprint(") created!\n"); } @@ -68,10 +111,10 @@ syscall_handler(struct sysc *call) { switch (call->type) { case SYSC_ECHO: - syscall_echo_h((struct sysc_echo *)call); + syscall_echo_h(call); break; case SYSC_NEW_THREAD: - syscall_new_thread_h((struct sysc_new_thread *)call); + syscall_new_thread_h(call); break; default: break; blob - 9c4f59ed470664e3583932f89f1a9e98980ec009 blob + 355b272393886987af96ba873b5cab4a4589205e --- servers/xhci/main.c +++ servers/xhci/main.c @@ -6,8 +6,14 @@ #include "libc.h" void -xhci_main() +xhci_main(struct contract *con) { output("xhci: running\n"); + + output("xhci: memory size is "); outputi(con->memSize); + output(" bytes\n"); + + output("Memory block location is : "); outputh((u64)con->memBlock[0]); output("\n"); + for (;;); } blob - d1edb04a4f5cfca5a1ece76b9ed6582ada0a95eb blob + 4814d52593d770131e8ced32171fbab5cca710de --- syscalls/syscalls.h +++ syscalls/syscalls.h @@ -1,19 +1,15 @@ #pragma once #define SYSC_BELL 0xE00000 +#define SYSC_ECHO_MSG_LEN 256 enum sysc_type { SYSC_ECHO, SYSC_NEW_THREAD, SYSC_FREE_THREAD, - SYSC_CONTEXT_SWITCH, // This shouldn't be a thing its for testing before APIC and thread states }; -struct sysc { - enum sysc_type type; -}; - -enum sysc_echo_type { +enum sysc_echo_cmd { SYSC_ECHO_STRING, SYSC_ECHO_INTEGER, SYSC_ECHO_HEXADECIMAL, @@ -21,30 +17,27 @@ enum sysc_echo_type { }; struct sysc_echo { - struct sysc sysc; - enum sysc_echo_type type; + enum sysc_echo_cmd cmd; union { - const char *msg; + u8 msg[SYSC_ECHO_MSG_LEN]; u64 number; }; }; struct sysc_new_thread { - struct sysc sysc; - void *entry; - u64 size; // Unused for now + void *entry; // Entry point + u64 memsize; + u64 seats; - s64 retid; // The threadId returned + s64 ret_id; }; -struct sysc_free_thread { - struct sysc sysc; - u64 id; +struct sysc { + enum sysc_type type; + union { + struct sysc_echo echo; + struct sysc_new_thread new_thread; + }; }; -struct sysc_context_switch { - struct sysc sysc; - u64 threadid; -}; - extern void (*sys_send)(struct sysc *call);