/** * @file protocol.hpp * @brief IPC protocol * * payload layout: [direction | RegionKey | Region] * IPC data share protocol layout : [ShMemhdr | large data] * Overall layout: [Payload | ShMemhdr | large data] * * device management layout: [ShmHdr | ShmCtx ...] * * @version 0.1 * @date 2025-10-29 * * @copyright Copyright (c) 2025 * */ #pragma once // #include // For mmap and munmap #include #include #include #include // #ifdef __cplusplus // #include // #define ALIGNAS(x) alignas(x) // #define ATOMIC_UINT32 std::atomic // #else // #include // #define ALIGNAS(x) _Alignas(x) // #define ATOMIC_UINT32 _Atomic uint32_t // #endif namespace calrt { extern const char* kSockPath; extern const char* kShMemCreatePath; extern const char* kShMemRepairPath; // inline constexpr const char* kSockPath = "/home/patrickyang/uds_epoll_demo.sock"; inline constexpr const char* kShMem = "/shm_calculet_device"; // inline constexpr const char* kShMemCreatePath = "/run/create_lck.lock"; // inline constexpr const char* kShMemRepairPath = "/run/repair.lock"; // inline constexpr const char* kShMemRepairPathBak = "/tmp/calrt/repair.lock"; // -------------------------------------- IPC large data transfer -------------------------------------- // /** * @brief each region key coresponse to one req or many if there are related. just tell the offset and size with same region id. * */ struct RegionKey { int32_t id; bool operator==(const RegionKey &other) const noexcept { return id == other.id; } }; struct Region { int32_t fd = -1; // don't init in client side int32_t prot; // = PROT_READ | PROT_WRITE; // protection flag for kernel. tell how process can access the mapped memory region int32_t flag; // = MAP_SHARED; std::atomic counter{0}; // counter if this region is still accessed uint64_t offset = 0; // temp represent memory address. uint64_t size = 0; void *map = nullptr; }; struct ShMemhdr { std::atomic ready = 0; // 0: not ready, 1: ready }; struct Payload { uint8_t direction; // 0: host-to-device. 1: device-to-host RegionKey key; Region region; }; // -------------------------------------- end -------------------------------------- // -------------------------------------- helper -------------------------------------- inline uint64_t now_ns() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return static_cast(ts.tv_sec) * 1000000000ull + ts.tv_nsec; } template void encode_impl(std::vector &meta, T data, size_t len = 0) { size_t n = meta.size(); size_t tSize = len == 0? sizeof(T) : len; meta.resize(n+tSize); std::memcpy(&meta[n], &data, tSize); } /** * @brief [id | prot | flag | size] * * @param meta * @param regionK * @param region */ inline void encode_socket(std::vector &meta, Payload &msgHdr) { encode_impl(meta, msgHdr.direction); encode_impl(meta, msgHdr.key.id); encode_impl(meta, msgHdr.region.prot); encode_impl(meta, msgHdr.region.flag); encode_impl(meta, msgHdr.region.size); encode_impl(meta, msgHdr.region.offset); } inline void decode_socket(const unsigned char* meta, Payload &out) { std::memcpy(&out.direction, meta, sizeof(out.direction)); size_t stride = sizeof(out.direction); std::memcpy(&out.key.id, meta+stride, sizeof(out.key.id)); stride += sizeof(out.key.id); std::memcpy(&out.region.prot, meta+stride, sizeof(out.region.prot)); stride += sizeof(out.region.prot); std::memcpy(&out.region.flag, meta+stride, sizeof(out.region.flag)); stride += sizeof(out.region.flag); std::memcpy(&out.region.size, meta+stride, sizeof(out.region.size)); stride += sizeof(out.region.size); std::memcpy(&out.region.offset, meta+stride, sizeof(out.region.offset)); } } //namespace calrt