Files

154 lines
4.3 KiB
C++

#pragma once
#include "abi/types.h"
#include "abi/syscalls.h"
#include "abi/ipc.h"
#include "stddef.h"
#include "stdint.h"
namespace ipc {
// Strongly typed result wrapper (no exceptions)
template <typename T>
struct Result {
sysret_t status;
T value;
constexpr bool is_ok() const noexcept { return status == SYS_OK; }
constexpr bool is_err() const noexcept { return status != SYS_OK; }
constexpr sysret_t error() const noexcept { return status; }
};
struct FastResponse {
uint64_t out0;
uint64_t out1;
};
struct IncomingRequest {
uint64_t sender_tid;
uint64_t opcode;
uint64_t arg0;
uint64_t arg1;
};
// RAII Capability Handle
class Capability {
private:
cap_t handle_;
public:
constexpr Capability() noexcept : handle_(CAP_NULL) {}
constexpr explicit Capability(cap_t handle) noexcept : handle_(handle) {}
~Capability() {
// Future: syscall to drop capability reference
}
Capability(const Capability&) = delete;
Capability& operator=(const Capability&) = delete;
constexpr Capability(Capability&& other) noexcept : handle_(other.handle_) {
other.handle_ = CAP_NULL;
}
constexpr Capability& operator=(Capability&& other) noexcept {
if (this != &other) {
handle_ = other.handle_;
other.handle_ = CAP_NULL;
}
return *this;
}
[[nodiscard]] constexpr cap_t get() const noexcept { return handle_; }
[[nodiscard]] constexpr bool is_valid() const noexcept { return handle_ != CAP_NULL; }
};
// RAII IPC Client Endpoint Wrapper
class Endpoint {
private:
Capability cap_;
public:
explicit Endpoint(Capability&& cap) noexcept : cap_(static_cast<Capability&&>(cap)) {}
explicit Endpoint(cap_t cap) noexcept : cap_(cap) {}
// Fast-path synchronous register call (zero allocations)
[[nodiscard]] Result<FastResponse> call(
uint64_t opcode,
uint64_t arg0 = 0,
uint64_t arg1 = 0,
uint64_t arg2 = 0,
uint64_t arg3 = 0
) const noexcept {
uint64_t out0 = 0;
uint64_t out1 = 0;
sysret_t ret = sys_ipc_call_raw(cap_.get(), opcode, arg0, arg1, arg2, arg3, &out0, &out1);
return Result<FastResponse>{ .status = ret, .value = { out0, out1 } };
}
[[nodiscard]] cap_t raw_handle() const noexcept { return cap_.get(); }
};
// RAII IPC Server Endpoint Wrapper
class ServerEndpoint {
private:
Capability cap_;
public:
explicit ServerEndpoint(Capability&& cap) noexcept : cap_(static_cast<Capability&&>(cap)) {}
explicit ServerEndpoint(cap_t cap) noexcept : cap_(cap) {}
// Server main loop: Reply to previous sender and wait for next request
[[nodiscard]] Result<IncomingRequest> reply_and_recv(
uint64_t reply_to_tid = 0,
uint64_t reply_val0 = 0,
uint64_t reply_val1 = 0
) const noexcept {
uint64_t sender_tid = 0;
uint64_t opcode = 0;
uint64_t arg0 = 0;
uint64_t arg1 = 0;
sysret_t ret = sys_ipc_reply_recv_raw(cap_.get(), reply_to_tid, reply_val0, reply_val1,
&sender_tid, &opcode, &arg0, &arg1);
return Result<IncomingRequest>{
.status = ret,
.value = { sender_tid, opcode, arg0, arg1 }
};
}
[[nodiscard]] cap_t raw_handle() const noexcept { return cap_.get(); }
};
// RAII Shared Memory Buffer
class SharedBuffer {
private:
Capability shm_cap_;
void* base_addr_;
size_t size_;
public:
SharedBuffer(Capability&& cap, void* addr, size_t sz) noexcept
: shm_cap_(static_cast<Capability&&>(cap)), base_addr_(addr), size_(sz) {}
~SharedBuffer() {
// Future: sys_unmap(base_addr_, size_)
}
SharedBuffer(const SharedBuffer&) = delete;
SharedBuffer& operator=(const SharedBuffer&) = delete;
SharedBuffer(SharedBuffer&& other) noexcept
: shm_cap_(static_cast<Capability&&>(other.shm_cap_)),
base_addr_(other.base_addr_),
size_(other.size_) {
other.base_addr_ = nullptr;
other.size_ = 0;
}
[[nodiscard]] void* data() const noexcept { return base_addr_; }
[[nodiscard]] size_t size() const noexcept { return size_; }
[[nodiscard]] cap_t handle() const noexcept { return shm_cap_.get(); }
};
} // namespace ipc