Improve IPC interface

This commit changes how IPC is interacted with in two ways:
* Simplify all buffers into just InputBuffer and OutputBuffer
* Use pushing/popping for data payload
This commit is contained in:
◱ PixelyIon
2019-11-24 00:18:22 +05:30
committed by ◱ PixelyIon
parent 745cb208a6
commit 38716989ae
26 changed files with 284 additions and 312 deletions

View File

@ -54,50 +54,6 @@ namespace skyline::gpu::device {
{"/dev/nvhost-ctrl-gpu", NvDeviceType::nvhost_ctrl_gpu}
};
/**
* @brief Describes a buffer by holding the address and size
*/
struct IoctlBuffer {
u64 address; //!< The address of the buffer
size_t size; //!< The size of the buffer
/**
* @param address The address of the buffer
* @param size The size of the buffer
*/
IoctlBuffer(u64 address, size_t size) : address(address), size(size) {}
};
/**
* @brief Wrapper around IoctlBuffer that loads in the address from a A Buffer Descriptor
*/
struct InputBuffer : public IoctlBuffer {
/**
* @param aBuf The A Buffer Descriptor that has contains the input data
*/
InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf) : IoctlBuffer(aBuf->Address(), aBuf->Size()) {}
/**
* @param aBuf The X Buffer Descriptor that has contains the input data
*/
InputBuffer(kernel::ipc::BufferDescriptorX *xBuf) : IoctlBuffer(xBuf->Address(), xBuf->size) {}
};
/**
* @brief Wrapper around IoctlBuffer that loads in the address from a B Buffer Descriptor
*/
struct OutputBuffer : public IoctlBuffer {
/**
* @param aBuf The B Buffer Descriptor that has to be outputted to
*/
OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf) : IoctlBuffer(bBuf->Address(), bBuf->Size()) {}
/**
* @param xBuf The C Buffer Descriptor that has to be outputted to
*/
OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf) : IoctlBuffer(cBuf->address, cBuf->size) {}
};
/**
* @brief This enumerates all the possible error codes returned by the Nvidia driver (https://switchbrew.org/wiki/NV_services#Errors)
*/
@ -128,11 +84,11 @@ namespace skyline::gpu::device {
};
/**
* @brief This holds all the IoctlBuffer objects in a coherent container
* @brief This holds all the input and output data for an IOCTL function
*/
struct IoctlBuffers {
std::vector<InputBuffer> input; //!< A vector of all input IOCTL buffers
std::vector<OutputBuffer> output; //!< A vector of all output IOCTL buffers
struct IoctlData {
std::vector<kernel::ipc::InputBuffer> input; //!< A vector of all input IOCTL buffers
std::vector<kernel::ipc::OutputBuffer> output; //!< A vector of all output IOCTL buffers
NvStatus status{NvStatus::Success}; //!< The error code that is returned to the application
/**
@ -140,19 +96,19 @@ namespace skyline::gpu::device {
* @param input An input buffer
* @param output An output buffer
*/
IoctlBuffers(InputBuffer input, OutputBuffer output) : input({input}), output({output}) {}
IoctlData(kernel::ipc::InputBuffer input, kernel::ipc::OutputBuffer output) : input({input}), output({output}) {}
/**
* @brief This constructor takes 1 input buffer, it's used for Ioctl sometimes
* @param output An output buffer
*/
IoctlBuffers(InputBuffer input) : input({input}) {}
IoctlData(kernel::ipc::InputBuffer input) : input({input}) {}
/**
* @brief This constructor takes 1 output buffer, it's used for Ioctl sometimes
* @param output An output buffer
*/
IoctlBuffers(OutputBuffer output) : output({output}) {}
IoctlData(kernel::ipc::OutputBuffer output) : output({output}) {}
/**
* @brief This constructor takes 2 input buffers and 1 output buffer, it's used for Ioctl1
@ -160,7 +116,7 @@ namespace skyline::gpu::device {
* @param input2 The second input buffer
* @param output An output buffer
*/
IoctlBuffers(InputBuffer input1, InputBuffer input2, OutputBuffer output) : input({input1, input2}), output({output}) {}
IoctlData(kernel::ipc::InputBuffer input1, kernel::ipc::InputBuffer input2, kernel::ipc::OutputBuffer output) : input({input1, input2}), output({output}) {}
/**
* @brief This constructor takes 1 input buffer and 2 output buffers, it's used for Ioctl2
@ -168,7 +124,7 @@ namespace skyline::gpu::device {
* @param output1 The first output buffer
* @param output2 The second output buffer
*/
IoctlBuffers(InputBuffer input, OutputBuffer output1, OutputBuffer output2) : input({input}), output({output1, output2}) {}
IoctlData(kernel::ipc::InputBuffer input, kernel::ipc::OutputBuffer output1, kernel::ipc::OutputBuffer output2) : input({input}), output({output1, output2}) {}
};
/**
@ -177,7 +133,7 @@ namespace skyline::gpu::device {
class NvDevice {
protected:
const DeviceState &state; //!< The state of the device
std::unordered_map<u32, std::function<void(IoctlBuffers &)>> vTable; //!< This holds the mapping from an Ioctl to the actual function
std::unordered_map<u32, std::function<void(IoctlData &)>> vTable; //!< This holds the mapping from an Ioctl to the actual function
public:
u16 refCount{1}; //!< The amount of handles to the device
@ -188,7 +144,7 @@ namespace skyline::gpu::device {
* @param deviceType The type of the device
* @param vTable The functions in this device
*/
NvDevice(const DeviceState &state, NvDeviceType deviceType, std::unordered_map<u32, std::function<void(IoctlBuffers &)>> vTable) : state(state), deviceType(deviceType), vTable(vTable) {}
NvDevice(const DeviceState &state, NvDeviceType deviceType, std::unordered_map<u32, std::function<void(IoctlData &)>> vTable) : state(state), deviceType(deviceType), vTable(vTable) {}
/**
* @brief This returns the name of the current service
@ -208,8 +164,8 @@ namespace skyline::gpu::device {
* @param cmd The IOCTL command that was called
* @param input The input to the IOCTL call
*/
void HandleIoctl(u32 cmd, IoctlBuffers &input) {
std::function<void(IoctlBuffers &)> function;
void HandleIoctl(u32 cmd, IoctlData &input) {
std::function<void(IoctlData &)> function;
try {
function = vTable.at(cmd);
} catch (std::out_of_range &) {

View File

@ -12,15 +12,15 @@ namespace skyline::gpu::device {
{0x40084714, NFUNC(NvHostChannel::SetUserData)}
}) {}
void NvHostChannel::SetNvmapFd(skyline::gpu::device::IoctlBuffers &buffer) {}
void NvHostChannel::SetNvmapFd(skyline::gpu::device::IoctlData &buffer) {}
void NvHostChannel::AllocObjCtx(skyline::gpu::device::IoctlBuffers &buffer) {}
void NvHostChannel::AllocObjCtx(skyline::gpu::device::IoctlData &buffer) {}
void NvHostChannel::ZcullBind(IoctlBuffers &buffer) {}
void NvHostChannel::ZcullBind(IoctlData &buffer) {}
void NvHostChannel::SetErrorNotifier(skyline::gpu::device::IoctlBuffers &buffer) {}
void NvHostChannel::SetErrorNotifier(skyline::gpu::device::IoctlData &buffer) {}
void NvHostChannel::SetPriority(skyline::gpu::device::IoctlBuffers &buffer) {
void NvHostChannel::SetPriority(skyline::gpu::device::IoctlData &buffer) {
auto priority = state.thisProcess->ReadMemory<NvChannelPriority>(buffer.input[0].address);
switch (priority) {
case NvChannelPriority::Low:
@ -35,8 +35,8 @@ namespace skyline::gpu::device {
}
}
void NvHostChannel::AllocGpfifoEx2(skyline::gpu::device::IoctlBuffers &buffer) {}
void NvHostChannel::AllocGpfifoEx2(skyline::gpu::device::IoctlData &buffer) {}
void NvHostChannel::SetUserData(skyline::gpu::device::IoctlBuffers &buffer) {}
void NvHostChannel::SetUserData(skyline::gpu::device::IoctlData &buffer) {}
}

View File

@ -22,36 +22,36 @@ namespace skyline::gpu::device {
/**
* @brief This sets the nvmap file descriptor (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD)
*/
void SetNvmapFd(IoctlBuffers &buffer);
void SetNvmapFd(IoctlData &buffer);
/**
* @brief This allocates a graphic context object (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX)
*/
void AllocObjCtx(IoctlBuffers &buffer);
void AllocObjCtx(IoctlData &buffer);
/**
* @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ZCULL_BIND)
*/
void ZcullBind(IoctlBuffers &buffer);
void ZcullBind(IoctlData &buffer);
/**
* @brief This initializes the error notifier for this channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_ERROR_NOTIFIER)
*/
void SetErrorNotifier(IoctlBuffers &buffer);
void SetErrorNotifier(IoctlData &buffer);
/**
* @brief This sets the priority of the channel (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_PRIORITY)
*/
void SetPriority(IoctlBuffers &buffer);
void SetPriority(IoctlData &buffer);
/**
* @brief This allocates a GPFIFO entry (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX2)
*/
void AllocGpfifoEx2(IoctlBuffers &buffer);
void AllocGpfifoEx2(IoctlData &buffer);
/**
* @brief This sets the user specific data (https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_USER_DATA)
*/
void SetUserData(IoctlBuffers &buffer);
void SetUserData(IoctlData &buffer);
};
}

View File

@ -10,12 +10,12 @@ namespace skyline::gpu::device {
{0x80084714, NFUNC(NvHostCtrlGpu::GetActiveSlotMask)}
}) {}
void NvHostCtrlGpu::ZCullGetCtxSize(IoctlBuffers &buffer) {
void NvHostCtrlGpu::ZCullGetCtxSize(IoctlData &buffer) {
u32 size = 0x1;
state.thisProcess->WriteMemory(size, buffer.output[0].address);
}
void NvHostCtrlGpu::ZCullGetInfo(skyline::gpu::device::IoctlBuffers &buffer) {
void NvHostCtrlGpu::ZCullGetInfo(skyline::gpu::device::IoctlData &buffer) {
struct {
u32 widthAlignPixels{0x20};
u32 heightAlignPixels{0x20};
@ -31,7 +31,7 @@ namespace skyline::gpu::device {
state.thisProcess->WriteMemory(zCullInfo, buffer.output[0].address);
}
void NvHostCtrlGpu::GetCharacteristics(IoctlBuffers &buffer) {
void NvHostCtrlGpu::GetCharacteristics(IoctlData &buffer) {
struct GpuCharacteristics {
u32 arch; // 0x120 (NVGPU_GPU_ARCH_GM200)
u32 impl; // 0xB (NVGPU_GPU_IMPL_GM20B) or 0xE (NVGPU_GPU_IMPL_GM20B_B)
@ -114,7 +114,7 @@ namespace skyline::gpu::device {
state.thisProcess->WriteMemory(data, buffer.output[0].address);
}
void NvHostCtrlGpu::GetTpcMasks(IoctlBuffers &buffer) {
void NvHostCtrlGpu::GetTpcMasks(IoctlData &buffer) {
struct Data {
u32 maskBufSize; // In
u32 reserved[3]; // In
@ -125,7 +125,7 @@ namespace skyline::gpu::device {
state.thisProcess->WriteMemory(data, buffer.output[0].address);
}
void NvHostCtrlGpu::GetActiveSlotMask(IoctlBuffers &buffer) {
void NvHostCtrlGpu::GetActiveSlotMask(IoctlData &buffer) {
struct Data {
u32 slot; // Out
u32 mask; // Out

View File

@ -13,26 +13,26 @@ namespace skyline::gpu::device {
/**
* @brief This returns a u32 GPU ZCULL Context Size (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE)
*/
void ZCullGetCtxSize(IoctlBuffers &buffer);
void ZCullGetCtxSize(IoctlData &buffer);
/**
* @brief This returns a the GPU ZCULL Information (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZCULL_GET_INFO)
*/
void ZCullGetInfo(IoctlBuffers &buffer);
void ZCullGetInfo(IoctlData &buffer);
/**
* @brief This returns a struct with certain GPU characteristics (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_CHARACTERISTICS)
*/
void GetCharacteristics(IoctlBuffers &buffer);
void GetCharacteristics(IoctlData &buffer);
/**
* @brief This returns the TPC mask value for each GPC (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_TPC_MASKS)
*/
void GetTpcMasks(IoctlBuffers &buffer);
void GetTpcMasks(IoctlData &buffer);
/**
* @brief This returns the mask value for a ZBC slot (https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_ZBC_GET_ACTIVE_SLOT_MASK)
*/
void GetActiveSlotMask(IoctlBuffers &buffer);
void GetActiveSlotMask(IoctlData &buffer);
};
}

View File

@ -13,7 +13,7 @@ namespace skyline::gpu::device {
{0xC008010E, NFUNC(NvMap::GetId)}
}) {}
void NvMap::Create(IoctlBuffers &buffer) {
void NvMap::Create(IoctlData &buffer) {
struct Data {
u32 size; // In
u32 handle; // Out
@ -24,7 +24,7 @@ namespace skyline::gpu::device {
state.logger->Debug("Create: Input: Size: 0x{:X}, Output: Handle: 0x{:X}, Status: {}", data.size, data.handle, buffer.status);
}
void NvMap::FromId(skyline::gpu::device::IoctlBuffers &buffer) {
void NvMap::FromId(skyline::gpu::device::IoctlData &buffer) {
struct Data {
u32 id; // In
u32 handle; // Out
@ -44,7 +44,7 @@ namespace skyline::gpu::device {
state.logger->Debug("FromId: Input: Handle: 0x{:X}, Output: ID: 0x{:X}, Status: {}", data.handle, data.id, buffer.status);
}
void NvMap::Alloc(IoctlBuffers &buffer) {
void NvMap::Alloc(IoctlData &buffer) {
struct Data {
u32 handle; // In
u32 heapMask; // In
@ -64,7 +64,7 @@ namespace skyline::gpu::device {
state.logger->Debug("Alloc: Input: Handle: 0x{:X}, HeapMask: 0x{:X}, Flags: {}, Align: 0x{:X}, Kind: {}, Address: 0x{:X}, Output: Status: {}", data.handle, data.heapMask, data.flags, data.align, data.kind, data.address, buffer.status);
}
void NvMap::Free(skyline::gpu::device::IoctlBuffers &buffer) {
void NvMap::Free(skyline::gpu::device::IoctlData &buffer) {
struct Data {
u32 handle; // In
u32 _pad0_;
@ -85,7 +85,7 @@ namespace skyline::gpu::device {
state.thisProcess->WriteMemory(data, buffer.output[0].address);
}
void NvMap::Param(IoctlBuffers &buffer) {
void NvMap::Param(IoctlData &buffer) {
enum class Parameter : u32 { Size = 1, Alignment = 2, Base = 3, HeapMask = 4, Kind = 5, Compr = 6 }; // https://android.googlesource.com/kernel/tegra/+/refs/heads/android-tegra-flounder-3.10-marshmallow/include/linux/nvmap.h#102
struct Data {
u32 handle; // In
@ -128,7 +128,7 @@ namespace skyline::gpu::device {
state.logger->Debug("Param: Input: Handle: 0x{:X}, Parameter: {}, Output: Result: 0x{:X}, Status: {}", data.handle, data.parameter, data.result, buffer.status);
}
void NvMap::GetId(skyline::gpu::device::IoctlBuffers &buffer) {
void NvMap::GetId(skyline::gpu::device::IoctlData &buffer) {
struct Data {
u32 id; // Out
u32 handle; // In

View File

@ -41,31 +41,31 @@ namespace skyline::gpu::device {
/**
* @brief This creates an NvMapObject and returns an handle to it (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_CREATE)
*/
void Create(IoctlBuffers &buffer);
void Create(IoctlData &buffer);
/**
* @brief This returns the handle of an NvMapObject from it's ID (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FROM_ID)
*/
void FromId(IoctlBuffers &buffer);
void FromId(IoctlData &buffer);
/**
* @brief This allocates memory for an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_ALLOC)
*/
void Alloc(IoctlBuffers &buffer);
void Alloc(IoctlData &buffer);
/**
* @brief This frees previously allocated memory (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_FREE)
*/
void Free(IoctlBuffers &buffer);
void Free(IoctlData &buffer);
/**
* @brief This returns a particular parameter from an NvMapObject (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_PARAM)
*/
void Param(IoctlBuffers &buffer);
void Param(IoctlData &buffer);
/**
* @brief This returns the ID of an NvMapObject from it's handle (https://switchbrew.org/wiki/NV_services#NVMAP_IOC_GET_ID)
*/
void GetId(IoctlBuffers &buffer);
void GetId(IoctlData &buffer);
};
}

View File

@ -34,7 +34,7 @@ namespace skyline::gpu {
state.thisProcess->ReadMemory(dataBuffer.data(), nvBuffer->address + gbpBuffer.offset, gbpBuffer.size);
}
BufferQueue::WaitContext::WaitContext(std::shared_ptr<kernel::type::KThread> thread, DequeueIn input, u64 address, u64 size) : thread(std::move(thread)), input(input), address(address), size(size) {}
BufferQueue::WaitContext::WaitContext(std::shared_ptr<kernel::type::KThread> thread, DequeueIn input, kernel::ipc::OutputBuffer& buffer) : thread(std::move(thread)), input(input), buffer(buffer) {}
BufferQueue::DequeueOut::DequeueOut(u32 slot) : slot(slot), _unk0_(0x1), _unk1_(0x24) {}
@ -49,7 +49,7 @@ namespace skyline::gpu {
state.logger->Debug("RequestBuffer: Slot: {}", slot, sizeof(GbpBuffer));
}
bool BufferQueue::DequeueBuffer(Parcel &in, Parcel &out, u64 address, u64 size) {
bool BufferQueue::DequeueBuffer(Parcel &in, Parcel &out, kernel::ipc::OutputBuffer& buffer) {
auto *data = reinterpret_cast<DequeueIn *>(in.data.data() + constant::TokenLength);
i64 slot{-1};
for (auto &buffer : queue) {
@ -60,7 +60,7 @@ namespace skyline::gpu {
}
if (slot == -1) {
state.thisThread->Sleep();
waitVec.emplace_back(state.thisThread, *data, address, size);
waitVec.emplace_back(state.thisThread, *data, buffer);
state.logger->Debug("DequeueBuffer: Width: {}, Height: {}, Format: {}, Usage: {}, Timestamps: {}, No Free Buffers", data->width, data->height, data->format, data->usage, data->timestamps);
return true;
}
@ -130,12 +130,12 @@ namespace skyline::gpu {
else {
auto context = waitVec.begin();
while (context != waitVec.end()) {
if (slot->resolution.width == context->input.width && slot->resolution.height == context->input.height && slot->gbpBuffer.format == context->input.format && slot->gbpBuffer.usage == context->input.usage) {
if (slot->resolution.width == context->input.width && slot->resolution.height == context->input.height && slot->gbpBuffer.usage == context->input.usage) {
context->thread->WakeUp();
gpu::Parcel out(state);
DequeueOut output(slotNo);
out.WriteData(output);
out.WriteParcel(context->address, context->size, context->thread->pid);
out.WriteParcel(context->buffer, context->thread->pid);
slot->status = BufferStatus::Dequeued;
waitVec.erase(context);
break;

View File

@ -160,16 +160,14 @@ namespace skyline::gpu {
struct WaitContext {
std::shared_ptr<kernel::type::KThread> thread; //!< The thread that is waiting on a buffer
DequeueIn input; //!< The input of DequeueBuffer
u64 address; //!< The address of the parcel buffer
u64 size; //!< The size of the parcel buffer
kernel::ipc::OutputBuffer buffer; //!< The output buffer to write the parcel into
/**
* @param thread The thread that is waiting on a buffer
* @param input The input of DequeueBuffer
* @param address The address of the parcel buffer
* @param size The size of the parcel buffer
* @param buffer The output buffer to write the parcel into
*/
WaitContext(std::shared_ptr<kernel::type::KThread> thread, DequeueIn input, u64 address, u64 size);
WaitContext(std::shared_ptr<kernel::type::KThread> thread, DequeueIn input, kernel::ipc::OutputBuffer& buffer);
};
std::vector<WaitContext> waitVec; //!< A vector of shared pointers to threads waiting on a buffer
@ -189,11 +187,10 @@ namespace skyline::gpu {
/**
* @brief This returns the slot of a free buffer
* @param address The address of the parcel buffer
* @param size The size of the parcel buffer
* @param buffer The output parcel buffer
* @return If the process is waiting for a buffer or not
*/
bool DequeueBuffer(Parcel &in, Parcel &out, u64 address, u64 size);
bool DequeueBuffer(Parcel &in, Parcel &out, kernel::ipc::OutputBuffer& buffer);
/**
* @brief This queues a buffer to be displayed

View File

@ -3,9 +3,7 @@
#include <kernel/types/KProcess.h>
namespace skyline::gpu {
Parcel::Parcel(kernel::ipc::BufferDescriptorABW *buffer, const DeviceState &state) : Parcel(buffer->Address(), buffer->Size(), state) {}
Parcel::Parcel(kernel::ipc::BufferDescriptorX *buffer, const DeviceState &state) : Parcel(buffer->Address(), buffer->size, state) {}
Parcel::Parcel(kernel::ipc::InputBuffer &buffer, const DeviceState &state) : Parcel(buffer.address, buffer.size, state) {}
Parcel::Parcel(u64 address, u64 size, const DeviceState &state) : state(state) {
state.thisProcess->ReadMemory(&header, address, sizeof(ParcelHeader));
@ -19,12 +17,8 @@ namespace skyline::gpu {
Parcel::Parcel(const DeviceState &state) : state(state) {}
u64 Parcel::WriteParcel(kernel::ipc::BufferDescriptorABW *buffer, pid_t process) {
return WriteParcel(buffer->Address(), buffer->Size(), process);
}
u64 Parcel::WriteParcel(kernel::ipc::BufferDescriptorC *buffer, pid_t process) {
return WriteParcel(buffer->address, buffer->size, process);
u64 Parcel::WriteParcel(kernel::ipc::OutputBuffer& buffer, pid_t process) {
return WriteParcel(buffer.address, buffer.size, process);
}
u64 Parcel::WriteParcel(u64 address, u64 maxSize, pid_t process) {

View File

@ -31,14 +31,7 @@ namespace skyline::gpu {
* @param buffer The buffer that contains the parcel
* @param state The state of the device
*/
Parcel(kernel::ipc::BufferDescriptorABW *buffer, const DeviceState &state);
/**
* @brief This constructor fills in the Parcel object with data from a IPC buffer
* @param buffer The buffer that contains the parcel
* @param state The state of the device
*/
Parcel(kernel::ipc::BufferDescriptorX *buffer, const DeviceState &state);
Parcel(kernel::ipc::InputBuffer &buffer, const DeviceState &state);
/**
* @brief This constructor fills in the Parcel object with data from a Parcel on a remote process
@ -85,20 +78,12 @@ namespace skyline::gpu {
}
/**
* @brief Writes the Parcel object into a particular B buffer on a process
* @brief Writes the Parcel object into a particular output buffer on a process
* @param buffer The buffer to write into
* @param process The process to write the Parcel to
* @return The total size of the message
*/
u64 WriteParcel(kernel::ipc::BufferDescriptorABW *buffer, pid_t process = 0);
/**
* @brief Writes the Parcel object into a particular C buffer on a process
* @param buffer The buffer to write into
* @param process The process to write the Parcel to
* @return The total size of the message
*/
u64 WriteParcel(kernel::ipc::BufferDescriptorC *buffer, pid_t process = 0);
u64 WriteParcel(kernel::ipc::OutputBuffer& buffer, pid_t process = 0);
/**
* @brief Writes the Parcel object into the process's memory