From 18d21a5f70ac94a8925aba6b88163ca7e0a5539a Mon Sep 17 00:00:00 2001 From: user Date: Tue, 24 Feb 2026 16:35:11 +0100 Subject: [PATCH] added IPC syscalls --- kernel/interrupt/guard.h | 4 ++ kernel/main.cc | 7 ++- kernel/memory/pageframealloc.cc | 2 + kernel/syscall/handler.cc | 11 +++++ kernel/syscall/skeleton.cc | 103 ++++++++++++++++++++++++++++++++++++++++ kernel/syscall/skeleton.h | 5 ++ kernel/syscall/stub.h | 20 +++++++- kernel/thread/thread.h | 18 +++++++ notes | 4 ++ 9 files changed, 171 insertions(+), 3 deletions(-) diff --git a/kernel/interrupt/guard.h b/kernel/interrupt/guard.h index d6b4997..777b49a 100644 --- a/kernel/interrupt/guard.h +++ b/kernel/interrupt/guard.h @@ -23,6 +23,10 @@ struct Vault { Bellringer bellringer; BBuffer keys; Semaphore keys_sem; + + Thread* thread_list[32]; + size_t thread_count = 0; + static constexpr int MAX_SEMS =32; Semaphore sems[MAX_SEMS]; diff --git a/kernel/main.cc b/kernel/main.cc index 02ccc47..6b51ecb 100644 --- a/kernel/main.cc +++ b/kernel/main.cc @@ -91,8 +91,13 @@ extern "C" int main() { uint32_t appsize = (*apps_header)[i]; uintptr_t appstart = (0x4000+offset)<<12; DBG << "app " << i << " size " << appsize << " at " << appstart << endl; - g.vault().scheduler.ready(new Thread(false, (void*)appstart, (appsize/4096)+1)); //TODO fix edgecase on size=4096 + + Thread* thread_ptr= new Thread(false, (void*)appstart, (appsize/4096)+1); //TODO fix edgecase on size=4096 + + g.vault().scheduler.ready(thread_ptr); //TODO fix edgecase on size=4096 offset += 1+(appsize/4096); + g.vault().thread_list[thread_ptr->id] = thread_ptr; + } g.vault().scheduler.ready(new Thread(false, (void*)0x4001000, 2)); diff --git a/kernel/memory/pageframealloc.cc b/kernel/memory/pageframealloc.cc index 6904087..09634d4 100644 --- a/kernel/memory/pageframealloc.cc +++ b/kernel/memory/pageframealloc.cc @@ -154,6 +154,8 @@ void PageFrameAllocator::free(PageFrame* frame){ //TODO ref counter etc... } + + void PageFrameAllocator::free(uintptr_t addr){ free(&PageFrames[addr>>12]); } diff --git a/kernel/syscall/handler.cc b/kernel/syscall/handler.cc index 229b13b..6c0b8bc 100644 --- a/kernel/syscall/handler.cc +++ b/kernel/syscall/handler.cc @@ -74,6 +74,17 @@ extern "C" size_t syscall_handler(size_t sysnum, size_t p1, size_t p2, return (size_t) Skeleton::map(&(Guard::enter().vault()), p1); case Syscall::ID::UNMAP: return (int) Skeleton::unmap(Guard::enter().vault(), (void*) (p1), p2); + case Syscall::ID::SEND: + return Skeleton::send(Guard::enter().vault(), static_cast(p1), reinterpret_cast(p2), p3, reinterpret_cast(p4), p5); + case Syscall::ID::RECEIVE: + return Skeleton::receive(Guard::enter().vault(), (void*)(p1), p2); + case Syscall::ID::REPLY: + return Skeleton::reply(Guard::enter().vault(), (void*)(p1), p2); + // case Syscall::ID::FORK: + // return Skeleton::fork(v, user); + break; + + } return static_cast(-1); diff --git a/kernel/syscall/skeleton.cc b/kernel/syscall/skeleton.cc index a424383..ef6e129 100644 --- a/kernel/syscall/skeleton.cc +++ b/kernel/syscall/skeleton.cc @@ -4,6 +4,7 @@ #include "../debug/output.h" #include "../device/textstream.h" #include "../interrupt/guard.h" +#include "../memory/page.h" #include "../sync/semaphore.h" #include "../thread/scheduler.h" #include "../memory/pageframealloc.h" @@ -283,5 +284,107 @@ namespace Syscall { } return 0; } + + +bool copy_from_phys(Vault& vault, uintptr_t phys_ptr, void* virt_ptr, size_t size) { + Thread* current_thread = vault.scheduler.active(); + + size_t offset = Page::offset(phys_ptr); + size_t total_size = size + offset; + four_lvl_paging_t* search_table = vault.scheduler.active()->paging_tree; + + void* page_ptr = getFreeVirtSpace(search_table, total_size); // page aligned pointer + if (page_ptr == nullptr) { + return false; + } + + uintptr_t virt_addr = (uintptr_t)(page_ptr) + offset; + for(uint8_t i =0; ipaging_tree); + } + + memcpy(virt_ptr, (void*)(virt_addr), size); + PageFrameAllocator::free((uintptr_t)(page_ptr)); + + return true; +} + + + +bool send(Vault& v, int pid, const void* sbuffer, size_t ssize, void* rbuffer, size_t rsize) { + Thread* current_thread = v.scheduler.active(); + Thread* target_thread = v.thread_list[pid]; + + uintptr_t sbuffer_ptr = (uintptr_t) target_thread->paging_tree; + + // Erstelle Nachichtenobjekt + IpcStruct msg = {sbuffer_ptr, ssize, current_thread->id, false, nullptr}; + + target_thread->ipc_queue.enqueue(msg); + target_thread->ipc_sem.v(v); + + while (true) { + current_thread->ipc_sem.p(v); + if (msg.is_answer) { + break; + } + DBG_VERBOSE << "" << endl; + } + + // Kopiere Antwort + if (!copy_from_phys(v, msg.ptr, rbuffer, rsize)) { + return false; + } + + return true; +} + +int receive(Vault& v, void* buffer, size_t size) { + + // DBG_VERBOSE << "Receive syscall for thread " << dec << v.scheduler.active()->id << endl; + Thread* thread = v.scheduler.active(); + + // Warte auf Nachricht + if (thread->ipc_queue.is_empty()) { + thread->ipc_sem.p(v); + } + + IpcStruct* ipc = thread->ipc_queue.first(); + if (ipc == nullptr) return -1; + + // Buffer holen + if (!copy_from_phys(v, ipc->ptr, buffer, size)) { + return -3; + } + + return ipc->pid; +} + +bool reply(Vault& v, const void* buffer, size_t size) { + + Thread* current_thread = v.scheduler.active(); + IpcStruct* ipc = current_thread->ipc_queue.dequeue(); + + // if (!ipc || ipc->pid < 0 || static_cast(ipc->pid) >= v.thread_count) return false; + + Thread* other_thread = v.thread_list[ipc->pid]; + if (other_thread == nullptr) return false; + + uintptr_t phys_ptr = (uintptr_t) current_thread->paging_tree; + + ipc->ptr = phys_ptr; + ipc->size = size; + ipc->pid = current_thread->id; + ipc->is_answer = true; + + // Sender aufwecken + other_thread->ipc_sem.v(v); + + return true; +} + + + + } // namespace Skeleton } // namespace Syscall diff --git a/kernel/syscall/skeleton.h b/kernel/syscall/skeleton.h index 65ac66e..6b0e0fb 100644 --- a/kernel/syscall/skeleton.h +++ b/kernel/syscall/skeleton.h @@ -26,6 +26,11 @@ void kill(Vault &vault, size_t pid); void* map(Vault *vault, size_t size); int unmap(Vault &vault, void* start, size_t size); void invlpg(uintptr_t virt_addr); +bool send(Vault &vault, int pid, const void* sbuffer, size_t ssize, void* rbuffer, size_t rsize); +int receive(Vault &vault, void* buffer, size_t size); +bool reply(Vault &vaul, const void* buffer, size_t size); +//int fork(Vault &vault, InterruptContext *user); + } // namespace Skeleton } // namespace Syscall diff --git a/kernel/syscall/stub.h b/kernel/syscall/stub.h index 4c6296c..ca90aaf 100644 --- a/kernel/syscall/stub.h +++ b/kernel/syscall/stub.h @@ -5,7 +5,7 @@ namespace Syscall { /*! \brief Syscall IDs * \note the syscall number must correspond to the values in the syscall stub! */ -enum class ID : size_t { + enum class ID : size_t { TEST = 0, WRITE = 1, READ = 2, @@ -18,7 +18,11 @@ enum class ID : size_t { SYS_EXIT = 9, SYS_KILL = 10, MAP = 11, - UNMAP = 12 + UNMAP = 12, + SEND = 13, + RECEIVE = 14, + REPLY = 15, + // FORK = 16 }; } // namespace Syscall @@ -81,3 +85,15 @@ extern "C" ssize_t sys_safe_call(Syscall::ID id, size_t p1, size_t p2, [[gnu::always_inline]] static inline int unmap(void* start, size_t size) { return sys_call(Syscall::ID::UNMAP, (size_t) start, size,0,0,0); } + +[[gnu::always_inline]] static inline bool send(int pid, const void* sbuffer, size_t ssize, void* rbuffer, size_t rsize) { + return sys_call(Syscall::ID::SEND, pid, (size_t)sbuffer, ssize, (size_t)rbuffer, rsize); +} + +[[gnu::always_inline]] static inline int receive(void* buffer, size_t size) { + return sys_call(Syscall::ID::RECEIVE, (size_t)buffer, size,0,0,0); +} + +[[gnu::always_inline]] static inline bool reply(const void* buffer, size_t size) { + return sys_call(Syscall::ID::REPLY, (size_t)buffer, size,0,0,0); +} diff --git a/kernel/thread/thread.h b/kernel/thread/thread.h index e410d8b..4d07572 100644 --- a/kernel/thread/thread.h +++ b/kernel/thread/thread.h @@ -16,12 +16,24 @@ #include "../arch/context.h" #include "../object/queue.h" #include "../types.h" +#include "../sync/semaphore.h" #include "../memory/pagetable.h" /// Stack size for each thread constexpr uint32_t STACK_SIZE = 3072; + +struct IpcStruct { + uintptr_t ptr; + size_t size; + int pid; + bool is_answer; + IpcStruct* queue_link = nullptr; +}; + + + /*! \brief The Thread is an object used by the scheduler. * \ingroup thread */ @@ -79,6 +91,12 @@ class Thread { pagetable_t* appcode_table; pagetable_t* appstack_table; + Semaphore ipc_sem; + Queue ipc_queue; + + + + /*! \brief Unique thread id */ const int id; diff --git a/notes b/notes index 64eb6d9..3a93b5e 100644 --- a/notes +++ b/notes @@ -17,3 +17,7 @@ l2 hier erhöhen falls wir mehr als 1gb brauchen. l1 512 + + + neue syscalls bei handler.cc skeleton.cc skeleton.h stub.h einbauen + done