mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-23 21:21:41 +00:00
.github
.vscode
Architecture
Core
Execute
FileSystem
Files
GUI
Library
Network
Profiling
Recovery
SystemCalls
Tasking
InterProcessCommunication.cpp
Scheduler.cpp
Security.cpp
Task.cpp
Tests
include
.gitignore
DAPI.hpp
Doxyfile
Fex.hpp
KConfig.cpp
KThread.cpp
Kernel.cpp
LICENSE
Makefile
README.md
dump.sh
ipc.h
kernel.h
syscalls.h
243 lines
6.9 KiB
C++
243 lines
6.9 KiB
C++
#include <ipc.hpp>
|
|
|
|
#include <task.hpp>
|
|
|
|
#include "../kernel.h"
|
|
#include "../ipc.h"
|
|
|
|
namespace InterProcessCommunication
|
|
{
|
|
IPCHandle *IPC::Create(IPCType Type, char UniqueToken[16])
|
|
{
|
|
SmartLock(this->IPCLock);
|
|
IPCHandle *Hnd = (IPCHandle *)mem->RequestPages(TO_PAGES(sizeof(IPCHandle)));
|
|
|
|
Hnd->ID = NextID++;
|
|
Hnd->Node = vfs->Create(UniqueToken, VirtualFileSystem::NodeFlags::FILE, IPCNode);
|
|
Hnd->Buffer = nullptr;
|
|
Hnd->Length = 0;
|
|
Hnd->Listening = false;
|
|
|
|
Handles.push_back(Hnd);
|
|
debug("Created IPC with ID %d", Hnd->ID);
|
|
return Hnd;
|
|
}
|
|
|
|
IPCErrorCode IPC::Destroy(IPCID ID)
|
|
{
|
|
SmartLock(this->IPCLock);
|
|
for (size_t i = 0; i < Handles.size(); i++)
|
|
{
|
|
if (Handles[i]->ID == ID)
|
|
{
|
|
vfs->Delete(Handles[i]->Node);
|
|
mem->FreePages(Handles[i], TO_PAGES(sizeof(IPCHandle)));
|
|
Handles.remove(i);
|
|
debug("Destroyed IPC with ID %d", ID);
|
|
return IPCSuccess;
|
|
}
|
|
}
|
|
debug("Failed to destroy IPC with ID %d", ID);
|
|
return IPCIDNotFound;
|
|
}
|
|
|
|
IPCErrorCode IPC::Allocate(IPCID ID, long Size)
|
|
{
|
|
SmartLock(this->IPCLock);
|
|
if (Size < 0)
|
|
return IPCError;
|
|
|
|
foreach (auto Hnd in Handles)
|
|
{
|
|
if (Hnd->ID == ID)
|
|
{
|
|
if (Hnd->Buffer != nullptr || Hnd->Length != 0)
|
|
return IPCAlreadyAllocated;
|
|
|
|
Hnd->Buffer = (uint8_t *)mem->RequestPages(TO_PAGES(Size));
|
|
Hnd->Length = Size;
|
|
return IPCSuccess;
|
|
}
|
|
}
|
|
return IPCIDNotFound;
|
|
}
|
|
|
|
IPCErrorCode IPC::Deallocate(IPCID ID)
|
|
{
|
|
SmartLock(this->IPCLock);
|
|
foreach (auto Hnd in Handles)
|
|
{
|
|
if (Hnd->ID == ID)
|
|
{
|
|
if (Hnd->Buffer == nullptr || Hnd->Length == 0)
|
|
return IPCNotAllocated;
|
|
|
|
mem->FreePages(Hnd->Buffer, TO_PAGES(Hnd->Length));
|
|
Hnd->Buffer = nullptr;
|
|
Hnd->Length = 0;
|
|
return IPCSuccess;
|
|
}
|
|
}
|
|
return IPCIDNotFound;
|
|
}
|
|
|
|
IPCErrorCode IPC::Read(IPCID ID, void *Buffer, long Size)
|
|
{
|
|
SmartLock(this->IPCLock);
|
|
if (Size < 0)
|
|
return IPCError;
|
|
|
|
foreach (auto Hnd in Handles)
|
|
{
|
|
if (Hnd->ID == ID)
|
|
{
|
|
if (Hnd->Listening)
|
|
{
|
|
debug("IPC %d is listening", ID);
|
|
return IPCNotListening;
|
|
}
|
|
if (Hnd->Length < Size)
|
|
{
|
|
debug("IPC %d is too small", ID);
|
|
return IPCError;
|
|
}
|
|
debug("IPC %d reading %d bytes", ID, Size);
|
|
memcpy(Buffer, Hnd->Buffer, Size);
|
|
debug("IPC read %d bytes", Size);
|
|
return IPCSuccess;
|
|
}
|
|
}
|
|
debug("IPC %d not found", ID);
|
|
return IPCIDNotFound;
|
|
}
|
|
|
|
IPCErrorCode IPC::Write(IPCID ID, void *Buffer, long Size)
|
|
{
|
|
SmartLock(this->IPCLock);
|
|
if (Size < 0)
|
|
{
|
|
debug("IPC %d is too small", ID);
|
|
return IPCError;
|
|
}
|
|
|
|
foreach (auto Hnd in Handles)
|
|
{
|
|
if (Hnd->ID == ID)
|
|
{
|
|
if (!Hnd->Listening)
|
|
{
|
|
debug("IPC %d is NOT listening", ID);
|
|
return IPCNotListening;
|
|
}
|
|
if (Hnd->Length < Size)
|
|
{
|
|
debug("IPC %d is too small", ID);
|
|
return IPCError;
|
|
}
|
|
debug("IPC %d writing %d bytes", ID, Size);
|
|
memcpy(Hnd->Buffer, Buffer, Size);
|
|
Hnd->Listening = false;
|
|
debug("IPC %d wrote %d bytes and now is %s", ID, Size, Hnd->Listening ? "listening" : "ready");
|
|
return IPCSuccess;
|
|
}
|
|
}
|
|
debug("IPC %d not found", ID);
|
|
return IPCIDNotFound;
|
|
}
|
|
|
|
IPCErrorCode IPC::Listen(IPCID ID, bool Listen)
|
|
{
|
|
foreach (auto Hnd in Handles)
|
|
{
|
|
if (Hnd->ID == ID)
|
|
{
|
|
Hnd->Listening = Listen;
|
|
debug("IPC %d is now set to %s", ID, Listen ? "listening" : "ready");
|
|
return IPCSuccess;
|
|
}
|
|
}
|
|
debug("IPC %d not found", ID);
|
|
return IPCIDNotFound;
|
|
}
|
|
|
|
IPCErrorCode IPC::Wait(IPCID ID)
|
|
{
|
|
foreach (auto Hnd in Handles)
|
|
{
|
|
if (Hnd->ID == ID)
|
|
{
|
|
if (!CPU::Interrupts())
|
|
warn("Interrupts are disabled. This may cause a kernel hang.");
|
|
debug("Waiting for IPC %d (now %s)", ID, Hnd->Listening ? "listening" : "ready");
|
|
while (Hnd->Listening)
|
|
CPU::Pause();
|
|
debug("IPC %d is ready", ID);
|
|
return IPCSuccess;
|
|
}
|
|
}
|
|
debug("IPC %d not found", ID);
|
|
return IPCIDNotFound;
|
|
}
|
|
|
|
IPCHandle *IPC::SearchByToken(char UniqueToken[16])
|
|
{
|
|
foreach (auto Hnd in Handles)
|
|
{
|
|
if (strcmp(Hnd->Node->Name, UniqueToken) == 0)
|
|
{
|
|
debug("Found IPC with token %s", UniqueToken);
|
|
return Hnd;
|
|
}
|
|
}
|
|
debug("Failed to find IPC with token %s", UniqueToken);
|
|
return nullptr;
|
|
}
|
|
|
|
int IPC::HandleSyscall(long Command, long Type, int ID, int Flags, void *Buffer, size_t Size)
|
|
{
|
|
switch (Command)
|
|
{
|
|
case IPC_CREATE:
|
|
{
|
|
char UniqueToken[16];
|
|
if (Buffer != nullptr)
|
|
strcpy(UniqueToken, (char *)Buffer);
|
|
else
|
|
snprintf(UniqueToken, 16, "IPC_%d", ID);
|
|
IPCHandle *Hnd = this->Create((IPCType)Type, UniqueToken);
|
|
this->Allocate(Hnd->ID, Size ? Size : PAGE_SIZE);
|
|
return Hnd->ID;
|
|
}
|
|
case IPC_READ:
|
|
return this->Read(ID, Buffer, Size);
|
|
case IPC_WRITE:
|
|
return TaskManager->GetProcessByID(Flags)->IPC->Write(ID, Buffer, Size);
|
|
case IPC_DELETE:
|
|
{
|
|
this->Deallocate(ID);
|
|
return this->Destroy(ID);
|
|
}
|
|
case IPC_WAIT:
|
|
return this->Wait(ID);
|
|
case IPC_LISTEN:
|
|
return this->Listen(ID, Flags);
|
|
default:
|
|
return IPCInvalidCommand;
|
|
}
|
|
return IPCError;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|