Kernel/Tasking/InterProcessCommunication.cpp
2023-02-07 03:22:44 +02:00

167 lines
4.3 KiB
C++

#include <ipc.hpp>
#include <task.hpp>
#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;
}
int IPC::HandleSyscall(long Command, long Type, int ID, int Flags, void *Buffer, size_t Size)
{
return 0;
}
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);
}
}