#include #include #include "../kernel.h" namespace InterProcessCommunication { IPCHandle *IPC::Create(IPCType Type, char UniqueToken[16]) { SmartLock(IPCLock); IPCHandle *Handle = (IPCHandle *)mem->RequestPages(TO_PAGES(sizeof(IPCHandle))); Handle->ID = NextID++; Handle->Node = vfs->Create(UniqueToken, VirtualFileSystem::NodeFlags::FILE, IPCNode); Handle->Node->Address = (uintptr_t)mem->RequestPages(TO_PAGES(sizeof(4096))); Handle->Node->Length = 4096; Handles.push_back(Handle); return Handle; } IPCErrorCode IPC::Destroy(IPCID ID) { SmartLock(IPCLock); for (size_t i = 0; i < Handles.size(); i++) { if (Handles[i]->ID == ID) { mem->FreePages(Handles[i], TO_PAGES(sizeof(IPCHandle))); Handles.remove(i); return IPCSuccess; } } return IPCIDNotFound; } IPCErrorCode IPC::Read(IPCID ID, uint8_t *Buffer, long Size) { SmartLock(IPCLock); if (Size < 0) return IPCError; foreach (auto Handle in Handles) { if (Handle->ID == ID) { if (Handle->Listening) return IPCNotListening; if (Handle->Length < Size) return IPCError; memcpy(Buffer, Handle->Buffer, Size); return IPCSuccess; } } return IPCIDNotFound; } IPCErrorCode IPC::Write(IPCID ID, uint8_t *Buffer, long Size) { SmartLock(IPCLock); if (Size < 0) return IPCError; foreach (auto Handle in Handles) { if (Handle->ID == ID) { if (!Handle->Listening) return IPCNotListening; if (Handle->Length < Size) return IPCError; memcpy(Handle->Buffer, Buffer, Size); Handle->Listening = false; return IPCSuccess; } } return IPCIDNotFound; } IPCErrorCode IPC::Listen(IPCID ID) { SmartLock(IPCLock); foreach (auto Handle in Handles) { if (Handle->ID == ID) { Handle->Listening = true; return IPCSuccess; } } return IPCIDNotFound; } IPCHandle *IPC::Wait(IPCID ID) { SmartLock(IPCLock); foreach (auto &Handle in Handles) { if (Handle->ID == ID) { while (Handle->Listening) CPU::Pause(); return Handle; } } return nullptr; } IPCErrorCode IPC::Allocate(IPCID ID, long Size) { SmartLock(IPCLock); if (Size < 0) return IPCError; foreach (auto Handle in Handles) { if (Handle->ID == ID) { if (Handle->Buffer != nullptr || Handle->Length != 0) return IPCAlreadyAllocated; Handle->Buffer = (uint8_t *)mem->RequestPages(TO_PAGES(Size)); Handle->Length = Size; return IPCSuccess; } } return IPCIDNotFound; } IPCErrorCode IPC::Deallocate(IPCID ID) { SmartLock(IPCLock); foreach (auto Handle in Handles) { if (Handle->ID == ID) { if (Handle->Buffer == nullptr || Handle->Length == 0) return IPCNotAllocated; mem->FreePages(Handle->Buffer, TO_PAGES(Handle->Length)); Handle->Buffer = nullptr; Handle->Length = 0; return IPCSuccess; } } return IPCIDNotFound; } IPC::IPC(void *Process) { this->Process = Process; mem = new Memory::MemMgr(nullptr, ((Tasking::PCB *)Process)->memDirectory); IPCNode = vfs->Create("ipc", VirtualFileSystem::NodeFlags::DIRECTORY, ((Tasking::PCB *)this->Process)->ProcessDirectory); } IPC::~IPC() { delete mem; vfs->Delete(IPCNode, true); } }