Updated IPC

This commit is contained in:
Alex 2023-02-10 16:30:45 +02:00
parent 7d37988e3c
commit 5bbef13d6a
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
3 changed files with 227 additions and 130 deletions

View File

@ -3,124 +3,59 @@
#include <task.hpp>
#include "../kernel.h"
#include "../ipc.h"
namespace InterProcessCommunication
{
IPCHandle *IPC::Create(IPCType Type, char UniqueToken[16])
{
SmartLock(IPCLock);
SmartLock(this->IPCLock);
IPCHandle *Hnd = (IPCHandle *)mem->RequestPages(TO_PAGES(sizeof(IPCHandle)));
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;
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(IPCLock);
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::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);
SmartLock(this->IPCLock);
if (Size < 0)
return IPCError;
foreach (auto Handle in Handles)
foreach (auto Hnd in Handles)
{
if (Handle->ID == ID)
if (Hnd->ID == ID)
{
if (Handle->Buffer != nullptr || Handle->Length != 0)
if (Hnd->Buffer != nullptr || Hnd->Length != 0)
return IPCAlreadyAllocated;
Handle->Buffer = (uint8_t *)mem->RequestPages(TO_PAGES(Size));
Handle->Length = Size;
Hnd->Buffer = (uint8_t *)mem->RequestPages(TO_PAGES(Size));
Hnd->Length = Size;
return IPCSuccess;
}
}
@ -129,26 +64,167 @@ namespace InterProcessCommunication
IPCErrorCode IPC::Deallocate(IPCID ID)
{
SmartLock(IPCLock);
foreach (auto Handle in Handles)
SmartLock(this->IPCLock);
foreach (auto Hnd in Handles)
{
if (Handle->ID == ID)
if (Hnd->ID == ID)
{
if (Handle->Buffer == nullptr || Handle->Length == 0)
if (Hnd->Buffer == nullptr || Hnd->Length == 0)
return IPCNotAllocated;
mem->FreePages(Handle->Buffer, TO_PAGES(Handle->Length));
Handle->Buffer = nullptr;
Handle->Length = 0;
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)
TaskManager->Schedule();
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)
{
return 0;
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)

View File

@ -5,6 +5,7 @@
#include <filesystem.hpp>
#include <vector.hpp>
#include <memory.hpp>
#include <atomic.hpp>
#include <lock.hpp>
namespace InterProcessCommunication
@ -27,7 +28,7 @@ namespace InterProcessCommunication
IPCSuccess,
IPCNotListening,
IPCTimeout,
IPCInvalidPort,
IPCInvalidCommand,
IPCAlreadyAllocated,
IPCNotAllocated,
IPCIDInUse,
@ -38,11 +39,10 @@ namespace InterProcessCommunication
struct IPCHandle
{
IPCID ID;
long Length;
uint8_t *Buffer;
bool Listening;
VirtualFileSystem::Node *Node;
IPCErrorCode Error;
void *Buffer;
long Length;
Atomic<bool> Listening;
};
class IPC
@ -56,18 +56,19 @@ namespace InterProcessCommunication
void *Process;
public:
IPC(void *Process);
~IPC();
int HandleSyscall(long Command, long Type, int ID, int Flags, void *Buffer, size_t Size);
IPCHandle *Create(IPCType Type, char UniqueToken[16]);
IPCErrorCode Destroy(IPCID ID);
IPCErrorCode Read(IPCID ID, uint8_t *Buffer, long Size);
IPCErrorCode Write(IPCID ID, uint8_t *Buffer, long Size);
IPCErrorCode Listen(IPCID ID);
IPCHandle *Wait(IPCID ID);
IPCErrorCode Allocate(IPCID ID, long Size);
IPCErrorCode Deallocate(IPCID ID);
IPCErrorCode Read(IPCID ID, void *Buffer, long Size);
IPCErrorCode Write(IPCID ID, void *Buffer, long Size);
IPCErrorCode Listen(IPCID ID, bool Listen);
IPCErrorCode Wait(IPCID ID);
IPCHandle *SearchByToken(char UniqueToken[16]);
int HandleSyscall(long Command, long Type, int ID, int Flags, void *Buffer, size_t Size);
IPC(void *Process);
~IPC();
};
}

64
ipc.h
View File

@ -4,35 +4,54 @@
enum IPCCommand
{
IPC_NULL,
/**
* @brief Create a new IPC
* Creating a new IPC will return a new ID for the IPC.
*
* @return The ID of the new IPC.
*/
IPC_CREATE,
/**
* @brief Read from IPC
* This will read from an IPC.
*/
IPC_READ,
/**
* @brief Write to IPC
* This will write to an IPC.
* @see Flags is used as process ID.
*/
IPC_WRITE,
IPC_DELETE,
IPC_GET,
IPC_SET,
IPC_GET_COUNT,
IPC_GET_SIZE,
IPC_GET_FLAGS,
IPC_SET_FLAGS,
IPC_GET_OWNER,
IPC_SET_OWNER,
IPC_GET_GROUP,
IPC_SET_GROUP,
IPC_GET_MODE,
IPC_SET_MODE,
IPC_GET_NAME,
IPC_SET_NAME,
IPC_GET_TYPE,
IPC_SET_TYPE,
IPC_GET_ID,
IPC_SET_ID,
IPC_GET_INDEX,
IPC_SET_INDEX,
/**
* @brief Wait for an IPC to be ready
* This will wait for an IPC to be ready to read/write.
* If it's message passing, it will wait for a message to be received.
*/
IPC_WAIT,
/**
* @brief Listen to a IPC
* @see Flags is used as a boolean
*/
IPC_LISTEN,
};
/* This must be a clone of IPCType inside ipc.hpp */
enum IPCType
{
IPC_TYPE_None,
/**
* @brief Message Passing
* Message passing is a way to send messages between processes.
*
*/
IPC_TYPE_MessagePassing,
IPC_TYPE_Port,
IPC_TYPE_SharedMemory,
@ -40,18 +59,19 @@ enum IPCType
IPC_TYPE_Socket
};
/* This must be a clone of IPCErrorCode inside ipc.hpp */
enum IPCErrorCode
{
IPC_E_CODE_Error = -1,
IPC_E_CODE_Success,
IPC_E_CODE_NotListening,
IPC_E_CODE_Timeout,
IPC_E_CODE_InvalidPort,
IPC_E_CODE_InvalidCommand,
IPC_E_CODE_AlreadyAllocated,
IPC_E_CODE_NotAllocated,
IPC_E_CODE_IDInUse,
IPC_E_CODE_IDNotRegistered,
IPC_E_CODE_IDNotFound
IPC_E_CODE_IDNotFound,
};
#endif // !__FENNIX_KERNEL_IPC_SYSCALLS_H__