mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
Updated IPC
This commit is contained in:
parent
7d37988e3c
commit
5bbef13d6a
@ -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)
|
||||
|
@ -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
64
ipc.h
@ -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__
|
||||
|
Loading…
x
Reference in New Issue
Block a user