diff --git a/stimBuffApis/livoxGen1/CMakeLists.txt b/stimBuffApis/livoxGen1/CMakeLists.txt index 3a0969e..44d88e8 100644 --- a/stimBuffApis/livoxGen1/CMakeLists.txt +++ b/stimBuffApis/livoxGen1/CMakeLists.txt @@ -6,6 +6,9 @@ if(ENABLE_STIMBUFFAPI_livoxGen1) # Set CONFIG variable for config.h set(CONFIG_STIMBUFFAPI_LIVOXGEN1_ENABLED 1) + # Find liburing using pkg-config + pkg_check_modules(URING REQUIRED liburing) + add_library(livoxGen1 SHARED livoxGen1.cpp stagingBuffer.cpp @@ -16,9 +19,14 @@ if(ENABLE_STIMBUFFAPI_livoxGen1) target_include_directories(livoxGen1 PUBLIC ${Boost_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/commonLibs + ${URING_INCLUDE_DIRS} ) target_link_libraries(livoxGen1 ${Boost_LIBRARIES} + ${URING_LIBRARIES} + ) + target_link_directories(livoxGen1 PUBLIC + ${URING_LIBRARY_DIRS} ) # Install rules diff --git a/stimBuffApis/livoxGen1/ioUringAssemblyEngine.cpp b/stimBuffApis/livoxGen1/ioUringAssemblyEngine.cpp index 64a064c..772fb3c 100644 --- a/stimBuffApis/livoxGen1/ioUringAssemblyEngine.cpp +++ b/stimBuffApis/livoxGen1/ioUringAssemblyEngine.cpp @@ -1,7 +1,9 @@ #include #include +#include #include #include "ioUringAssemblyEngine.h" +#include "pcloudStimulusBuffer.h" namespace smo { namespace stim_buff { @@ -22,16 +24,90 @@ struct DummyLivoxEthHeader uint8_t timestamp[8]; }; +IoUringAssemblyEngine::IoUringAssemblyEngine(PcloudStimulusBuffer& parent_) +: parent(parent_), +frameAssemblyDesc(nullptr), ring{}, +isSetup(false), +stallTimer(parent_.device->componentThread->getIoService()) +{} + +bool IoUringAssemblyEngine::setup() +{ + if (isSetup) + { return false; } + + // Get FrameAssemblyDesc from staging buffer + frameAssemblyDesc = static_cast>( + parent.stagingBuffer); + + if (!frameAssemblyDesc || frameAssemblyDesc->slots.empty()) + { return false; } + + // Get UDP socket file descriptor + int udpFd = parent.device->pcloudDataSocketDesc->native_handle(); + if (udpFd < 0) + { return false; } + + /** EXPLANATION: + * Initialize io_uring ring - allocate SQEs and CQEs for one frame assembly + * One SQE per slot (one datagram per slot) + */ + int ret = io_uring_queue_init( + static_cast(frameAssemblyDesc->numSlots), &ring, 0); + if (ret < 0) + { return false; } + + isSetup = true; + return true; +} + +void IoUringAssemblyEngine::finalize() +{ + // Call stop() to cancel in-flight operations (stop() already cancels the timer) + stop(); + + // Clean up io_uring ring if it was initialized + if (isSetup) + { + io_uring_queue_exit(&ring); + isSetup = false; + } + + // Reset state to allow setup() to be called again + frameAssemblyDesc = nullptr; +} + +void IoUringAssemblyEngine::resetAndAssembleFrame() +{ + // Design/stub: This method should: + // 1. Submit frameAssemblyDesc->numSlots RECVMSG SQEs using io_uring_prep_recvmsg() + // - Each SQE receives into frameAssemblyDesc->slots[i].vaddr + // - With size frameAssemblyDesc->slots[i].nBytes + // - Socket FD from parent.device->pcloudDataSocketDesc->native_handle() + // 2. Submit batch via io_uring_submit(&ring) + // 3. Set up stall timer using stallTimer with appropriate timeout + // - SQEs are independent and can arrive out of order + // - Timer detects if SQEs get stalled +} + +void IoUringAssemblyEngine::stop() +{ + // Design/stub: This method should: + // 1. Cancel all pending SQEs using io_uring cancellation mechanisms + // 2. Cancel in-flight stall timeout timer via stallTimer.cancel() + // 3. Set appropriate state flags +} + void IoUringAssemblyEngine::cancelIncompleteAndFillDummies() { - if (!desc) + if (!frameAssemblyDesc) { return; } - for (size_t i = 0; i < desc->numSlots; ++i) + for (size_t i = 0; i < frameAssemblyDesc->numSlots; ++i) { // In the real path, decide from CQE accounting whether slot i completed. // Here, demonstrate dummy header insertion API. - auto* hdr = reinterpret_cast(desc->slots[i].vaddr); + auto* hdr = reinterpret_cast(frameAssemblyDesc->slots[i].vaddr); hdr->err_code = DummyLivoxEthHeader::INVALID_ERR_CODE; hdr->timestamp_type = DummyLivoxEthHeader::INVALID_TIMESTAMP_TYPE; hdr->data_type = DummyLivoxEthHeader::INVALID_DATA_TYPE; diff --git a/stimBuffApis/livoxGen1/ioUringAssemblyEngine.h b/stimBuffApis/livoxGen1/ioUringAssemblyEngine.h index 0d8e983..258afdb 100644 --- a/stimBuffApis/livoxGen1/ioUringAssemblyEngine.h +++ b/stimBuffApis/livoxGen1/ioUringAssemblyEngine.h @@ -8,28 +8,45 @@ #include #include #include - +#include +#include +#include #include - #include "frameAssemblyDesc.h" namespace smo { namespace stim_buff { +class PcloudStimulusBuffer; + class IoUringAssemblyEngine { public: - IoUringAssemblyEngine(); + explicit IoUringAssemblyEngine(PcloudStimulusBuffer& parent); ~IoUringAssemblyEngine() = default; + bool setup(); + void finalize(); + void resetAndAssembleFrame(); + void stop(); + // Telemetry helpers static size_t computePointsPerDgram(int returnMode); static size_t computePointsPerFrame(int returnMode, size_t nDgramsPerFrame) { return computePointsPerDgram(returnMode) * nDgramsPerFrame; } private: + PcloudStimulusBuffer& parent; + // Cached descriptor for reuse across iterations - FrameAssemblyDesc* desc; + std::shared_ptr frameAssemblyDesc; + + // io_uring infrastructure + struct io_uring ring; + bool isSetup; + + // Stall detection timer + boost::asio::deadline_timer stallTimer; void cancelIncompleteAndFillDummies(); };