diff --git a/Tasking/InterProcessCommunication.cpp b/Tasking/InterProcessCommunication.cpp index a3d2939..dcb1333 100644 --- a/Tasking/InterProcessCommunication.cpp +++ b/Tasking/InterProcessCommunication.cpp @@ -3,124 +3,59 @@ #include #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) diff --git a/include/ipc.hpp b/include/ipc.hpp index fe0b4e3..efc9927 100644 --- a/include/ipc.hpp +++ b/include/ipc.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include 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 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(); }; } diff --git a/ipc.h b/ipc.h index 9d241c4..368e6c6 100644 --- a/ipc.h +++ b/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__