mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Updated IPC
This commit is contained in:
parent
7d37988e3c
commit
5bbef13d6a
@ -3,124 +3,59 @@
|
|||||||
#include <task.hpp>
|
#include <task.hpp>
|
||||||
|
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
|
#include "../ipc.h"
|
||||||
|
|
||||||
namespace InterProcessCommunication
|
namespace InterProcessCommunication
|
||||||
{
|
{
|
||||||
IPCHandle *IPC::Create(IPCType Type, char UniqueToken[16])
|
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)));
|
Hnd->ID = NextID++;
|
||||||
Handle->ID = NextID++;
|
Hnd->Node = vfs->Create(UniqueToken, VirtualFileSystem::NodeFlags::FILE, IPCNode);
|
||||||
Handle->Node = vfs->Create(UniqueToken, VirtualFileSystem::NodeFlags::FILE, IPCNode);
|
Hnd->Buffer = nullptr;
|
||||||
Handle->Node->Address = (uintptr_t)mem->RequestPages(TO_PAGES(sizeof(4096)));
|
Hnd->Length = 0;
|
||||||
Handle->Node->Length = 4096;
|
Hnd->Listening = false;
|
||||||
Handles.push_back(Handle);
|
|
||||||
return Handle;
|
Handles.push_back(Hnd);
|
||||||
|
debug("Created IPC with ID %d", Hnd->ID);
|
||||||
|
return Hnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCErrorCode IPC::Destroy(IPCID ID)
|
IPCErrorCode IPC::Destroy(IPCID ID)
|
||||||
{
|
{
|
||||||
SmartLock(IPCLock);
|
SmartLock(this->IPCLock);
|
||||||
for (size_t i = 0; i < Handles.size(); i++)
|
for (size_t i = 0; i < Handles.size(); i++)
|
||||||
{
|
{
|
||||||
if (Handles[i]->ID == ID)
|
if (Handles[i]->ID == ID)
|
||||||
{
|
{
|
||||||
|
vfs->Delete(Handles[i]->Node);
|
||||||
mem->FreePages(Handles[i], TO_PAGES(sizeof(IPCHandle)));
|
mem->FreePages(Handles[i], TO_PAGES(sizeof(IPCHandle)));
|
||||||
Handles.remove(i);
|
Handles.remove(i);
|
||||||
|
debug("Destroyed IPC with ID %d", ID);
|
||||||
return IPCSuccess;
|
return IPCSuccess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
debug("Failed to destroy IPC with ID %d", ID);
|
||||||
return IPCIDNotFound;
|
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)
|
IPCErrorCode IPC::Allocate(IPCID ID, long Size)
|
||||||
{
|
{
|
||||||
SmartLock(IPCLock);
|
SmartLock(this->IPCLock);
|
||||||
if (Size < 0)
|
if (Size < 0)
|
||||||
return IPCError;
|
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;
|
return IPCAlreadyAllocated;
|
||||||
|
|
||||||
Handle->Buffer = (uint8_t *)mem->RequestPages(TO_PAGES(Size));
|
Hnd->Buffer = (uint8_t *)mem->RequestPages(TO_PAGES(Size));
|
||||||
Handle->Length = Size;
|
Hnd->Length = Size;
|
||||||
return IPCSuccess;
|
return IPCSuccess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,26 +64,167 @@ namespace InterProcessCommunication
|
|||||||
|
|
||||||
IPCErrorCode IPC::Deallocate(IPCID ID)
|
IPCErrorCode IPC::Deallocate(IPCID ID)
|
||||||
{
|
{
|
||||||
SmartLock(IPCLock);
|
SmartLock(this->IPCLock);
|
||||||
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 IPCNotAllocated;
|
return IPCNotAllocated;
|
||||||
|
|
||||||
mem->FreePages(Handle->Buffer, TO_PAGES(Handle->Length));
|
mem->FreePages(Hnd->Buffer, TO_PAGES(Hnd->Length));
|
||||||
Handle->Buffer = nullptr;
|
Hnd->Buffer = nullptr;
|
||||||
Handle->Length = 0;
|
Hnd->Length = 0;
|
||||||
return IPCSuccess;
|
return IPCSuccess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return IPCIDNotFound;
|
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)
|
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)
|
IPC::IPC(void *Process)
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <filesystem.hpp>
|
#include <filesystem.hpp>
|
||||||
#include <vector.hpp>
|
#include <vector.hpp>
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
|
#include <atomic.hpp>
|
||||||
#include <lock.hpp>
|
#include <lock.hpp>
|
||||||
|
|
||||||
namespace InterProcessCommunication
|
namespace InterProcessCommunication
|
||||||
@ -27,7 +28,7 @@ namespace InterProcessCommunication
|
|||||||
IPCSuccess,
|
IPCSuccess,
|
||||||
IPCNotListening,
|
IPCNotListening,
|
||||||
IPCTimeout,
|
IPCTimeout,
|
||||||
IPCInvalidPort,
|
IPCInvalidCommand,
|
||||||
IPCAlreadyAllocated,
|
IPCAlreadyAllocated,
|
||||||
IPCNotAllocated,
|
IPCNotAllocated,
|
||||||
IPCIDInUse,
|
IPCIDInUse,
|
||||||
@ -38,11 +39,10 @@ namespace InterProcessCommunication
|
|||||||
struct IPCHandle
|
struct IPCHandle
|
||||||
{
|
{
|
||||||
IPCID ID;
|
IPCID ID;
|
||||||
long Length;
|
|
||||||
uint8_t *Buffer;
|
|
||||||
bool Listening;
|
|
||||||
VirtualFileSystem::Node *Node;
|
VirtualFileSystem::Node *Node;
|
||||||
IPCErrorCode Error;
|
void *Buffer;
|
||||||
|
long Length;
|
||||||
|
Atomic<bool> Listening;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPC
|
class IPC
|
||||||
@ -56,18 +56,19 @@ namespace InterProcessCommunication
|
|||||||
void *Process;
|
void *Process;
|
||||||
|
|
||||||
public:
|
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]);
|
IPCHandle *Create(IPCType Type, char UniqueToken[16]);
|
||||||
IPCErrorCode Destroy(IPCID ID);
|
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 Allocate(IPCID ID, long Size);
|
||||||
IPCErrorCode Deallocate(IPCID ID);
|
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
|
enum IPCCommand
|
||||||
{
|
{
|
||||||
IPC_NULL,
|
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,
|
IPC_CREATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read from IPC
|
||||||
|
* This will read from an IPC.
|
||||||
|
*/
|
||||||
IPC_READ,
|
IPC_READ,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write to IPC
|
||||||
|
* This will write to an IPC.
|
||||||
|
* @see Flags is used as process ID.
|
||||||
|
*/
|
||||||
IPC_WRITE,
|
IPC_WRITE,
|
||||||
|
|
||||||
IPC_DELETE,
|
IPC_DELETE,
|
||||||
IPC_GET,
|
|
||||||
IPC_SET,
|
/**
|
||||||
IPC_GET_COUNT,
|
* @brief Wait for an IPC to be ready
|
||||||
IPC_GET_SIZE,
|
* This will wait for an IPC to be ready to read/write.
|
||||||
IPC_GET_FLAGS,
|
* If it's message passing, it will wait for a message to be received.
|
||||||
IPC_SET_FLAGS,
|
*/
|
||||||
IPC_GET_OWNER,
|
IPC_WAIT,
|
||||||
IPC_SET_OWNER,
|
|
||||||
IPC_GET_GROUP,
|
/**
|
||||||
IPC_SET_GROUP,
|
* @brief Listen to a IPC
|
||||||
IPC_GET_MODE,
|
* @see Flags is used as a boolean
|
||||||
IPC_SET_MODE,
|
*/
|
||||||
IPC_GET_NAME,
|
IPC_LISTEN,
|
||||||
IPC_SET_NAME,
|
|
||||||
IPC_GET_TYPE,
|
|
||||||
IPC_SET_TYPE,
|
|
||||||
IPC_GET_ID,
|
|
||||||
IPC_SET_ID,
|
|
||||||
IPC_GET_INDEX,
|
|
||||||
IPC_SET_INDEX,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* This must be a clone of IPCType inside ipc.hpp */
|
||||||
enum IPCType
|
enum IPCType
|
||||||
{
|
{
|
||||||
IPC_TYPE_None,
|
IPC_TYPE_None,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Message Passing
|
||||||
|
* Message passing is a way to send messages between processes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
IPC_TYPE_MessagePassing,
|
IPC_TYPE_MessagePassing,
|
||||||
IPC_TYPE_Port,
|
IPC_TYPE_Port,
|
||||||
IPC_TYPE_SharedMemory,
|
IPC_TYPE_SharedMemory,
|
||||||
@ -40,18 +59,19 @@ enum IPCType
|
|||||||
IPC_TYPE_Socket
|
IPC_TYPE_Socket
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* This must be a clone of IPCErrorCode inside ipc.hpp */
|
||||||
enum IPCErrorCode
|
enum IPCErrorCode
|
||||||
{
|
{
|
||||||
IPC_E_CODE_Error = -1,
|
IPC_E_CODE_Error = -1,
|
||||||
IPC_E_CODE_Success,
|
IPC_E_CODE_Success,
|
||||||
IPC_E_CODE_NotListening,
|
IPC_E_CODE_NotListening,
|
||||||
IPC_E_CODE_Timeout,
|
IPC_E_CODE_Timeout,
|
||||||
IPC_E_CODE_InvalidPort,
|
IPC_E_CODE_InvalidCommand,
|
||||||
IPC_E_CODE_AlreadyAllocated,
|
IPC_E_CODE_AlreadyAllocated,
|
||||||
IPC_E_CODE_NotAllocated,
|
IPC_E_CODE_NotAllocated,
|
||||||
IPC_E_CODE_IDInUse,
|
IPC_E_CODE_IDInUse,
|
||||||
IPC_E_CODE_IDNotRegistered,
|
IPC_E_CODE_IDNotRegistered,
|
||||||
IPC_E_CODE_IDNotFound
|
IPC_E_CODE_IDNotFound,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_IPC_SYSCALLS_H__
|
#endif // !__FENNIX_KERNEL_IPC_SYSCALLS_H__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user